blob: cd279c7455f6d715996346d89c2068c0201a7c82 [file] [log] [blame]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001#!/usr/bin/perl
2###########################################################################
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04003# ABI Compliance Checker (ACC) 1.99.8.4
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-2010 The Linux Foundation
7# Copyright (C) 2009-2011 Institute for System Programming, RAS
8# Copyright (C) 2011-2012 Nokia Corporation and/or its subsidiary(-ies)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009# Copyright (C) 2011-2013 ROSA 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 Ponomarenko989a50b2012-04-03 12:24:22 +040020# - G++ (3.0-4.7, recommended 4.5 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 Ponomarenko989a50b2012-04-03 12:24:22 +040030# - MinGW (3.0-4.7, recommended 4.5 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 Ponomarenkof442c172013-07-30 19:08:11 +040041# ABI Dumper >= 0.98
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 Ponomarenko2b029aa2013-09-27 15:31:42 +040067my $TOOL_VERSION = "1.99.8.4";
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 Ponomarenkofe00e7e2013-05-24 16:48:30 +040070my $XML_REPORT_VERSION = "1.1";
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,
87%RelativeDirectory, $TargetLibraryFName, $TestDump, $CheckImpl, $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 Ponomarenko07aea072012-11-12 16:15:07 +040094$SourceReportPath, $UseXML, $Browse, $OpenReport, $SortDump, $DumpFormat,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040095$ExtraInfo, $ExtraDump, $Force, $Tolerance, $Tolerant, $SkipSymbolsListPath,
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040096$CheckInfo, $Quick, $AffectLimit, $AllAffected, $CppIncompat);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040097
98my $CmdName = get_filename($0);
99my %OS_LibExt = (
100 "dynamic" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400101 "linux"=>"so",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400102 "macos"=>"dylib",
103 "windows"=>"dll",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400104 "symbian"=>"dso",
105 "default"=>"so"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400106 },
107 "static" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400108 "linux"=>"a",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400109 "windows"=>"lib",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400110 "symbian"=>"lib",
111 "default"=>"a"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400112 }
113);
114
115my %OS_Archive = (
116 "windows"=>"zip",
117 "default"=>"tar.gz"
118);
119
120my %ERROR_CODE = (
121 # Compatible verdict
122 "Compatible"=>0,
123 "Success"=>0,
124 # Incompatible verdict
125 "Incompatible"=>1,
126 # Undifferentiated error code
127 "Error"=>2,
128 # System command is not found
129 "Not_Found"=>3,
130 # Cannot access input files
131 "Access_Error"=>4,
132 # Cannot compile header files
133 "Cannot_Compile"=>5,
134 # Header compiled with errors
135 "Compile_Error"=>6,
136 # Invalid input ABI dump
137 "Invalid_Dump"=>7,
138 # Incompatible version of ABI dump
139 "Dump_Version"=>8,
140 # Cannot find a module
141 "Module_Error"=>9,
142 # Empty intersection between
143 # headers and shared objects
144 "Empty_Intersection"=>10,
145 # Empty set of symbols in headers
146 "Empty_Set"=>11
147);
148
149my %HomePage = (
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400150 "Wiki"=>"http://ispras.linuxbase.org/index.php/ABI_compliance_checker",
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400151 "Dev1"=>"https://github.com/lvc/abi-compliance-checker",
152 "Dev2"=>"http://forge.ispras.ru/projects/abi-compliance-checker"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400153);
154
155my $ShortUsage = "ABI Compliance Checker (ACC) $TOOL_VERSION
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400156A tool for checking backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400157Copyright (C) 2012 ROSA Laboratory
158License: 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 Ponomarenko989a50b2012-04-03 12:24:22 +0400219 "cross-gcc|gcc-path=s" => \$CrossGcc,
220 "cross-prefix|gcc-prefix=s" => \$CrossPrefix,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400221 "sysroot=s" => \$SystemRoot_Opt,
222 "v1|version1|vnum=s" => \$TargetVersion{1},
223 "v2|version2=s" => \$TargetVersion{2},
224 "s|strict!" => \$StrictCompat,
225 "symbols-list=s" => \$SymbolsListPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400226 "skip-symbols=s" => \$SkipSymbolsListPath,
227 "headers-list=s" => \$TargetHeadersPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400228 "skip-headers=s" => \$SkipHeadersPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400229 "header=s" => \$TargetHeader,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400230 "headers-only|headers_only!" => \$CheckHeadersOnly_Opt,
231 "objects-only!" => \$CheckObjectsOnly_Opt,
232 "check-impl|check-implementation!" => \$CheckImpl,
233 "show-retval!" => \$ShowRetVal,
234 "use-dumps!" => \$UseDumps,
235 "nostdinc!" => \$NoStdInc,
236 "dump-system=s" => \$DumpSystem,
237 "sysinfo=s" => \$TargetSysInfo,
238 "cmp-systems!" => \$CmpSystems,
239 "libs-list=s" => \$TargetLibsPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400240 "ext|extended!" => \$ExtendedCheck,
241 "q|quiet!" => \$Quiet,
242 "stdout!" => \$StdOut,
243 "report-format=s" => \$ReportFormat,
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400244 "dump-format=s" => \$DumpFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400245 "xml!" => \$UseXML,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400246 "lang=s" => \$UserLang,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400247 "binary|bin|abi!" => \$BinaryOnly,
248 "source|src|api!" => \$SourceOnly,
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400249 "limit-affected|affected-limit=s" => \$AffectLimit,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400250# other options
251 "test!" => \$TestTool,
252 "test-dump!" => \$TestDump,
253 "debug!" => \$Debug,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400254 "cpp-compatible!" => \$CppCompat,
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +0400255 "cpp-incompatible!" => \$CppIncompat,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400256 "p|params=s" => \$ParamNamesPath,
257 "relpath1|relpath=s" => \$RelativeDirectory{1},
258 "relpath2=s" => \$RelativeDirectory{2},
259 "dump-path=s" => \$OutputDumpPath,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400260 "sort!" => \$SortDump,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400261 "report-path=s" => \$OutputReportPath,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400262 "bin-report-path=s" => \$BinaryReportPath,
263 "src-report-path=s" => \$SourceReportPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400264 "log-path=s" => \$LoggingPath,
265 "log1-path=s" => \$OutputLogPath{1},
266 "log2-path=s" => \$OutputLogPath{2},
267 "logging-mode=s" => \$LogMode,
268 "list-affected!" => \$ListAffected,
269 "l-full|lib-full=s" => \$TargetLibraryFName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400270 "component=s" => \$TargetComponent_Opt,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400271 "b|browse=s" => \$Browse,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400272 "open!" => \$OpenReport,
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,
280 "all-affected!" => \$AllAffected
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400281) or ERR_MESSAGE();
282
283sub ERR_MESSAGE()
284{
285 printMsg("INFO", "\n".$ShortUsage);
286 exit($ERROR_CODE{"Error"});
287}
288
289my $LIB_TYPE = $UseStaticLibs?"static":"dynamic";
290my $SLIB_TYPE = $LIB_TYPE;
291if($OSgroup!~/macos|windows/ and $SLIB_TYPE eq "dynamic")
292{ # show as "shared" library
293 $SLIB_TYPE = "shared";
294}
295my $LIB_EXT = getLIB_EXT($OSgroup);
296my $AR_EXT = getAR_EXT($OSgroup);
297my $BYTE_SIZE = 8;
298my $COMMON_LOG_PATH = "logs/run.log";
299
300my $HelpMessage="
301NAME:
302 ABI Compliance Checker ($CmdName)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400303 Check backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400304
305DESCRIPTION:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400306 ABI Compliance Checker (ACC) is a tool for checking backward binary and
307 source-level compatibility of a $SLIB_TYPE C/C++ library. The tool checks
308 header files and $SLIB_TYPE libraries (*.$LIB_EXT) of old and new versions and
309 analyzes changes in API and ABI (ABI=API+compiler ABI) that may break binary
310 and/or source-level compatibility: changes in calling stack, v-table changes,
311 removed symbols, renamed fields, etc. Binary incompatibility may result in
312 crashing or incorrect behavior of applications built with an old version of
313 a library if they run on a new one. Source incompatibility may result in
314 recompilation errors with a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400315
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400316 The tool is intended for developers of software libraries and maintainers
317 of operating systems who are interested in ensuring backward compatibility,
318 i.e. allow old applications to run or to be recompiled with newer library
319 versions.
320
321 Also the tool can be used by ISVs for checking applications portability to
322 new library versions. Found issues can be taken into account when adapting
323 the application to a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400324
325 This tool is free software: you can redistribute it and/or modify it
326 under the terms of the GNU LGPL or GNU GPL.
327
328USAGE:
329 $CmdName [options]
330
331EXAMPLE:
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400332 $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400333
334 OLD.xml and NEW.xml are XML-descriptors:
335
336 <version>
337 1.0
338 </version>
339
340 <headers>
341 /path1/to/header(s)/
342 /path2/to/header(s)/
343 ...
344 </headers>
345
346 <libs>
347 /path1/to/library(ies)/
348 /path2/to/library(ies)/
349 ...
350 </libs>
351
352INFORMATION OPTIONS:
353 -h|-help
354 Print this help.
355
356 -i|-info
357 Print complete info.
358
359 -v|-version
360 Print version information.
361
362 -dumpversion
363 Print the tool version ($TOOL_VERSION) and don't do anything else.
364
365GENERAL OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400366 -l|-lib|-library NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400367 Library name (without version).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400368
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400369 -d1|-old|-o PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400370 Descriptor of 1st (old) library version.
371 It may be one of the following:
372
373 1. XML-descriptor (VERSION.xml file):
374
375 <version>
376 1.0
377 </version>
378
379 <headers>
380 /path1/to/header(s)/
381 /path2/to/header(s)/
382 ...
383 </headers>
384
385 <libs>
386 /path1/to/library(ies)/
387 /path2/to/library(ies)/
388 ...
389 </libs>
390
391 ... (XML-descriptor template
392 can be generated by -d option)
393
394 2. ABI dump generated by -dump option
395 3. Directory with headers and/or $SLIB_TYPE libraries
396 4. Single header file
397 5. Single $SLIB_TYPE library
398 6. Comma separated list of headers and/or libraries
399
400 If you are using an 2-6 descriptor types then you should
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400401 specify version numbers with -v1 and -v2 options too.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400402
403 For more information, please see:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400404 http://ispras.linuxbase.org/index.php/Library_Descriptor
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400405
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400406 -d2|-new|-n PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400407 Descriptor of 2nd (new) library version.
408
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400409 -dump|-dump-abi PATH
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400410 Create library ABI dump for the input XML descriptor. You can
411 transfer it anywhere and pass instead of the descriptor. Also
412 it can be used for debugging the tool.
413
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400414 Supported ABI dump versions: 2.0<=V<=$ABI_DUMP_VERSION
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400415
416 -old-dumps
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400417 Enable support for old-version ABI dumps ($OLDEST_SUPPORTED_VERSION<=V<2.0).\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400418
419sub HELP_MESSAGE() {
420 printMsg("INFO", $HelpMessage."
421MORE INFO:
422 $CmdName --info\n");
423}
424
425sub INFO_MESSAGE()
426{
427 printMsg("INFO", "$HelpMessage
428EXTRA OPTIONS:
429 -d|-descriptor-template
430 Create XML-descriptor template ./VERSION.xml
431
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400432 -app|-application PATH
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200433 This option allows one to specify the application that should be checked
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400434 for portability to the new library version.
435
436 -static-libs
437 Check static libraries instead of the shared ones. The <libs> section
438 of the XML-descriptor should point to static libraries location.
439
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400440 -cross-gcc|-gcc-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400441 Path to the cross GCC compiler to use instead of the usual (host) GCC.
442
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400443 -cross-prefix|-gcc-prefix PREFIX
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400444 GCC toolchain prefix.
445
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400446 -sysroot DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400447 Specify the alternative root directory. The tool will search for include
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400448 paths in the DIR/usr/include and DIR/usr/lib directories.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400449
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400450 -v1|-version1 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400451 Specify 1st library version outside the descriptor. This option is needed
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200452 if you have preferred an alternative descriptor type (see -d1 option).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400453
454 In general case you should specify it in the XML-descriptor:
455 <version>
456 VERSION
457 </version>
458
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400459 -v2|-version2 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400460 Specify 2nd library version outside the descriptor.
461
462 -s|-strict
463 Treat all compatibility warnings as problems. Add a number of \"Low\"
464 severity problems to the return value of the tool.
465
466 -headers-only
467 Check header files without $SLIB_TYPE libraries. It is easy to run, but may
468 provide a low quality compatibility report with false positives and
469 without detecting of added/removed symbols.
470
471 Alternatively you can write \"none\" word to the <libs> section
472 in the XML-descriptor:
473 <libs>
474 none
475 </libs>
476
477 -objects-only
478 Check $SLIB_TYPE libraries without header files. It is easy to run, but may
479 provide a low quality compatibility report with false positives and
480 without analysis of changes in parameters and data types.
481
482 Alternatively you can write \"none\" word to the <headers> section
483 in the XML-descriptor:
484 <headers>
485 none
486 </headers>
487
488 -check-impl|-check-implementation
489 Compare canonified disassembled binary code of $SLIB_TYPE libraries to
490 detect changes in the implementation. Add \'Problems with Implementation\'
491 section to the report.
492
493 -show-retval
494 Show the symbol's return type in the report.
495
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400496 -symbols-list PATH
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200497 This option allows one to specify a file with a list of symbols (mangled
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400498 names in C++) that should be checked, other symbols will not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400499
500 -skip-symbols PATH
501 The list of symbols that should NOT be checked.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400502
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400503 -headers-list PATH
504 The file with a list of headers, that should be checked/dumped.
505
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400506 -skip-headers PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400507 The file with the list of header files, that should not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400508
509 -header NAME
510 Check/Dump ABI of this header only.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400511
512 -use-dumps
513 Make dumps for two versions of a library and compare dumps. This should
514 increase the performance of the tool and decrease the system memory usage.
515
516 -nostdinc
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400517 Do not search in GCC standard system directories for header files.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400518
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400519 -dump-system NAME -sysroot DIR
520 Find all the shared libraries and header files in DIR directory,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400521 create XML descriptors and make ABI dumps for each library. The result
522 set of ABI dumps can be compared (--cmp-systems) with the other one
523 created for other version of operating system in order to check them for
524 compatibility. Do not forget to specify -cross-gcc option if your target
525 system requires some specific version of GCC compiler (different from
526 the host GCC). The system ABI dump will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400527 sys_dumps/NAME/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400528
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400529 -dump-system DESCRIPTOR.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400530 The same as the previous option but takes an XML descriptor of the target
531 system as input, where you should describe it:
532
533 /* Primary sections */
534
535 <name>
536 /* Name of the system */
537 </name>
538
539 <headers>
540 /* The list of paths to header files and/or
541 directories with header files, one per line */
542 </headers>
543
544 <libs>
545 /* The list of paths to shared libraries and/or
546 directories with shared libraries, one per line */
547 </libs>
548
549 /* Optional sections */
550
551 <search_headers>
552 /* List of directories to be searched
553 for header files to automatically
554 generate include paths, one per line */
555 </search_headers>
556
557 <search_libs>
558 /* List of directories to be searched
559 for shared libraries to resolve
560 dependencies, one per line */
561 </search_libs>
562
563 <tools>
564 /* List of directories with tools used
565 for analysis (GCC toolchain), one per line */
566 </tools>
567
568 <cross_prefix>
569 /* GCC toolchain prefix.
570 Examples:
571 arm-linux-gnueabi
572 arm-none-symbianelf */
573 </cross_prefix>
574
575 <gcc_options>
576 /* Additional GCC options, one per line */
577 </gcc_options>
578
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400579 -sysinfo DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400580 This option may be used with -dump-system to dump ABI of operating
581 systems and configure the dumping process.
582 Default:
583 modules/Targets/{unix, symbian, windows}
584
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400585 -cmp-systems -d1 sys_dumps/NAME1/ARCH -d2 sys_dumps/NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400586 Compare two system ABI dumps. Create compatibility reports for each
587 library and the common HTML report including the summary of test
588 results for all checked libraries. Report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400589 sys_compat_reports/NAME1_to_NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400590
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400591 -libs-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400592 The file with a list of libraries, that should be dumped by
593 the -dump-system option or should be checked by the -cmp-systems option.
594
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400595 -ext|-extended
596 If your library A is supposed to be used by other library B and you
597 want to control the ABI of B, then you should enable this option. The
598 tool will check for changes in all data types, even if they are not
599 used by any function in the library A. Such data types are not part
600 of the A library ABI, but may be a part of the ABI of the B library.
601
602 The short scheme is:
603 app C (broken) -> lib B (broken ABI) -> lib A (stable ABI)
604
605 -q|-quiet
606 Print all messages to the file instead of stdout and stderr.
607 Default path (can be changed by -log-path option):
608 $COMMON_LOG_PATH
609
610 -stdout
611 Print analysis results (compatibility reports and ABI dumps) to stdout
612 instead of creating a file. This would allow piping data to other programs.
613
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400614 -report-format FMT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400615 Change format of compatibility report.
616 Formats:
617 htm - HTML format (default)
618 xml - XML format
619
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400620 -dump-format FMT
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400621 Change format of ABI dump.
622 Formats:
623 perl - Data::Dumper format (default)
624 xml - XML format
625
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400626 -xml
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400627 Alias for: --report-format=xml or --dump-format=xml
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400628
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400629 -lang LANG
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400630 Set library language (C or C++). You can use this option if the tool
631 cannot auto-detect a language. This option may be useful for checking
632 C-library headers (--lang=C) in --headers-only or --extended modes.
633
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400634 -binary|-bin|-abi
635 Show \"Binary\" compatibility problems only.
636 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400637 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400638
639 -source|-src|-api
640 Show \"Source\" compatibility problems only.
641 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400642 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400643
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400644 -limit-affected LIMIT
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400645 The maximum number of affected symbols listed under the description
646 of the changed type in the report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400647
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400648OTHER OPTIONS:
649 -test
650 Run internal tests. Create two binary incompatible versions of a sample
651 library and run the tool to check them for compatibility. This option
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200652 allows one to check if the tool works correctly in the current environment.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400653
654 -test-dump
655 Test ability to create, read and compare ABI dumps.
656
657 -debug
658 Debugging mode. Print debug info on the screen. Save intermediate
659 analysis stages in the debug directory:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400660 debug/LIB_NAME/VERSION/
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400661
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400662 Also consider using --dump option for debugging the tool.
663
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400664 -cpp-compatible
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400665 If your header files are written in C language and can be compiled
666 by the G++ compiler (i.e. don't use C++ keywords), then you can tell
667 the tool about this and speedup the analysis.
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +0400668
669 -cpp-incompatible
670 Set this option if input C header files use C++ keywords.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400671
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400672 -p|-params PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400673 Path to file with the function parameter names. It can be used
674 for improving report view if the library header files have no
675 parameter names. File format:
676
677 func1;param1;param2;param3 ...
678 func2;param1;param2;param3 ...
679 ...
680
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400681 -relpath PATH
682 Replace {RELPATH} macros to PATH in the XML-descriptor used
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400683 for dumping the library ABI (see -dump option).
684
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400685 -relpath1 PATH
686 Replace {RELPATH} macros to PATH in the 1st XML-descriptor (-d1).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400687
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400688 -relpath2 PATH
689 Replace {RELPATH} macros to PATH in the 2nd XML-descriptor (-d2).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400690
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400691 -dump-path PATH
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400692 Specify a *.abi.$AR_EXT or *.abi file path where to generate an ABI dump.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400693 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400694 abi_dumps/LIB_NAME/LIB_NAME_VERSION.abi.$AR_EXT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400695
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400696 -sort
697 Enable sorting of data in ABI dumps.
698
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400699 -report-path PATH
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400700 Path to compatibility report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400701 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400702 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400703
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400704 -bin-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400705 Path to \"Binary\" compatibility report.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400706 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400707 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400708
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400709 -src-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400710 Path to \"Source\" compatibility report.
711 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400712 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400713
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400714 -log-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400715 Log path for all messages.
716 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400717 logs/LIB_NAME/VERSION/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400718
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400719 -log1-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400720 Log path for 1st version of a library.
721 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400722 logs/LIB_NAME/V1/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400723
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400724 -log2-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400725 Log path for 2nd version of a library.
726 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400727 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400728
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400729 -logging-mode MODE
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400730 Change logging mode.
731 Modes:
732 w - overwrite old logs (default)
733 a - append old logs
734 n - do not write any logs
735
736 -list-affected
737 Generate file with the list of incompatible
738 symbols beside the HTML compatibility report.
739 Use 'c++filt \@file' command from GNU binutils
740 to unmangle C++ symbols in the generated file.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400741 Default names:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400742 abi_affected.txt
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400743 src_affected.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400744
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400745 -component NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400746 The component name in the title and summary of the HTML report.
747 Default:
748 library
749
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400750 -l-full|-lib-full NAME
751 Change library name in the report title to NAME. By default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400752 will be displayed a name specified by -l option.
753
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400754 -b|-browse PROGRAM
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400755 Open report(s) in the browser (firefox, opera, etc.).
756
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400757 -open
758 Open report(s) in the default browser.
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400759
760 -extra-info DIR
761 Dump extra info to DIR.
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400762
763 -extra-dump
764 Create extended ABI dump containing all symbols
765 from the translation unit.
766
767 -force
768 Try to use this option if the tool doesn't work.
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400769
770 -tolerance LEVEL
771 Apply a set of heuristics to successfully compile input
772 header files. You can enable several tolerance levels by
773 joining them into one string (e.g. 13, 124, etc.).
774 Levels:
775 1 - skip non-Linux headers (e.g. win32_*.h, etc.)
776 2 - skip internal headers (e.g. *_p.h, impl/*.h, etc.)
777 3 - skip headers that iclude non-Linux headers
778 4 - skip headers included by others
779
780 -tolerant
781 Enable highest tolerance level [1234].
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400782
783 -check
784 Check completeness of the ABI dump.
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400785
786 -quick
787 Quick analysis. Disable check of some template instances.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400788
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400789REPORT:
790 Compatibility report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400791 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400792
793 Log will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400794 logs/LIB_NAME/V1/log.txt
795 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400796
797EXIT CODES:
798 0 - Compatible. The tool has run without any errors.
799 non-zero - Incompatible or the tool has run with errors.
800
801REPORT BUGS TO:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400802 Andrey Ponomarenko <aponomarenko\@rosalab.ru>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400803
804MORE INFORMATION:
805 ".$HomePage{"Wiki"}."
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400806 ".$HomePage{"Dev1"}."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400807}
808
809my $DescriptorTemplate = "
810<?xml version=\"1.0\" encoding=\"utf-8\"?>
811<descriptor>
812
813/* Primary sections */
814
815<version>
816 /* Version of the library */
817</version>
818
819<headers>
820 /* The list of paths to header files and/or
821 directories with header files, one per line */
822</headers>
823
824<libs>
825 /* The list of paths to shared libraries (*.$LIB_EXT) and/or
826 directories with shared libraries, one per line */
827</libs>
828
829/* Optional sections */
830
831<include_paths>
832 /* The list of include paths that will be provided
833 to GCC to compile library headers, one per line.
834 NOTE: If you define this section then the tool
835 will not automatically generate include paths */
836</include_paths>
837
838<add_include_paths>
839 /* The list of include paths that will be added
840 to the automatically generated include paths, one per line */
841</add_include_paths>
842
843<skip_include_paths>
844 /* The list of include paths that will be removed from the
845 list of automatically generated include paths, one per line */
846</skip_include_paths>
847
848<gcc_options>
849 /* Additional GCC options, one per line */
850</gcc_options>
851
852<include_preamble>
853 /* The list of header files that will be
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +0400854 included before other headers, one per line */
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400855</include_preamble>
856
857<defines>
858 /* The list of defines that will be added at the
859 headers compiling stage, one per line:
860 #define A B
861 #define C D */
862</defines>
863
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +0400864<add_namespaces>
865 /* The list of namespaces that should be added to the alanysis
866 if the tool cannot find them automatically, one per line */
867</add_namespaces>
868
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400869<skip_types>
870 /* The list of data types, that
871 should not be checked, one per line */
872</skip_types>
873
874<skip_symbols>
875 /* The list of functions (mangled/symbol names in C++),
876 that should not be checked, one per line */
877</skip_symbols>
878
879<skip_namespaces>
880 /* The list of C++ namespaces, that
881 should not be checked, one per line */
882</skip_namespaces>
883
884<skip_constants>
885 /* The list of constants that should
886 not be checked, one name per line */
887</skip_constants>
888
889<skip_headers>
890 /* The list of header files and/or directories
891 with header files that should not be checked, one per line */
892</skip_headers>
893
894<skip_libs>
895 /* The list of shared libraries and/or directories
896 with shared libraries that should not be checked, one per line */
897</skip_libs>
898
899<skip_including>
900 /* The list of header files, that cannot be included
901 directly (or non-self compiled ones), one per line */
902</skip_including>
903
904<search_headers>
905 /* List of directories to be searched
906 for header files to automatically
907 generate include paths, one per line. */
908</search_headers>
909
910<search_libs>
911 /* List of directories to be searched
912 for shared librariess to resolve
913 dependencies, one per line */
914</search_libs>
915
916<tools>
917 /* List of directories with tools used
918 for analysis (GCC toolchain), one per line */
919</tools>
920
921<cross_prefix>
922 /* GCC toolchain prefix.
923 Examples:
924 arm-linux-gnueabi
925 arm-none-symbianelf */
926</cross_prefix>
927
928</descriptor>";
929
930my %Operator_Indication = (
931 "not" => "~",
932 "assign" => "=",
933 "andassign" => "&=",
934 "orassign" => "|=",
935 "xorassign" => "^=",
936 "or" => "|",
937 "xor" => "^",
938 "addr" => "&",
939 "and" => "&",
940 "lnot" => "!",
941 "eq" => "==",
942 "ne" => "!=",
943 "lt" => "<",
944 "lshift" => "<<",
945 "lshiftassign" => "<<=",
946 "rshiftassign" => ">>=",
947 "call" => "()",
948 "mod" => "%",
949 "modassign" => "%=",
950 "subs" => "[]",
951 "land" => "&&",
952 "lor" => "||",
953 "rshift" => ">>",
954 "ref" => "->",
955 "le" => "<=",
956 "deref" => "*",
957 "mult" => "*",
958 "preinc" => "++",
959 "delete" => " delete",
960 "vecnew" => " new[]",
961 "vecdelete" => " delete[]",
962 "predec" => "--",
963 "postinc" => "++",
964 "postdec" => "--",
965 "plusassign" => "+=",
966 "plus" => "+",
967 "minus" => "-",
968 "minusassign" => "-=",
969 "gt" => ">",
970 "ge" => ">=",
971 "new" => " new",
972 "multassign" => "*=",
973 "divassign" => "/=",
974 "div" => "/",
975 "neg" => "-",
976 "pos" => "+",
977 "memref" => "->*",
978 "compound" => "," );
979
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400980my %UnknownOperator;
981
982my %NodeType= (
983 "array_type" => "Array",
984 "binfo" => "Other",
985 "boolean_type" => "Intrinsic",
986 "complex_type" => "Intrinsic",
987 "const_decl" => "Other",
988 "enumeral_type" => "Enum",
989 "field_decl" => "Other",
990 "function_decl" => "Other",
991 "function_type" => "FunctionType",
992 "identifier_node" => "Other",
993 "integer_cst" => "Other",
994 "integer_type" => "Intrinsic",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400995 "vector_type" => "Vector",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400996 "method_type" => "MethodType",
997 "namespace_decl" => "Other",
998 "parm_decl" => "Other",
999 "pointer_type" => "Pointer",
1000 "real_cst" => "Other",
1001 "real_type" => "Intrinsic",
1002 "record_type" => "Struct",
1003 "reference_type" => "Ref",
1004 "string_cst" => "Other",
1005 "template_decl" => "Other",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001006 "template_type_parm" => "TemplateParam",
1007 "typename_type" => "TypeName",
1008 "sizeof_expr" => "SizeOf",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001009 "tree_list" => "Other",
1010 "tree_vec" => "Other",
1011 "type_decl" => "Other",
1012 "union_type" => "Union",
1013 "var_decl" => "Other",
1014 "void_type" => "Intrinsic",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001015 "nop_expr" => "Other", #
1016 "addr_expr" => "Other", #
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001017 "offset_type" => "Other" );
1018
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001019my %CppKeywords_C = map {$_=>1} (
1020 # C++ 2003 keywords
1021 "public",
1022 "protected",
1023 "private",
1024 "default",
1025 "template",
1026 "new",
1027 #"asm",
1028 "dynamic_cast",
1029 "auto",
1030 "try",
1031 "namespace",
1032 "typename",
1033 "using",
1034 "reinterpret_cast",
1035 "friend",
1036 "class",
1037 "virtual",
1038 "const_cast",
1039 "mutable",
1040 "static_cast",
1041 "export",
1042 # C++0x keywords
1043 "noexcept",
1044 "nullptr",
1045 "constexpr",
1046 "static_assert",
1047 "explicit",
1048 # cannot be used as a macro name
1049 # as it is an operator in C++
1050 "and",
1051 #"and_eq",
1052 "not",
1053 #"not_eq",
1054 "or"
1055 #"or_eq",
1056 #"bitand",
1057 #"bitor",
1058 #"xor",
1059 #"xor_eq",
1060 #"compl"
1061);
1062
1063my %CppKeywords_F = map {$_=>1} (
1064 "delete",
1065 "catch",
1066 "alignof",
1067 "thread_local",
1068 "decltype",
1069 "typeid"
1070);
1071
1072my %CppKeywords_O = map {$_=>1} (
1073 "bool",
1074 "register",
1075 "inline",
1076 "operator"
1077);
1078
1079my %CppKeywords_A = map {$_=>1} (
1080 "this",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001081 "throw",
1082 "template"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001083);
1084
1085foreach (keys(%CppKeywords_C),
1086keys(%CppKeywords_F),
1087keys(%CppKeywords_O)) {
1088 $CppKeywords_A{$_}=1;
1089}
1090
1091# Header file extensions as described by gcc
1092my $HEADER_EXT = "h|hh|hp|hxx|hpp|h\\+\\+";
1093
1094my %IntrinsicMangling = (
1095 "void" => "v",
1096 "bool" => "b",
1097 "wchar_t" => "w",
1098 "char" => "c",
1099 "signed char" => "a",
1100 "unsigned char" => "h",
1101 "short" => "s",
1102 "unsigned short" => "t",
1103 "int" => "i",
1104 "unsigned int" => "j",
1105 "long" => "l",
1106 "unsigned long" => "m",
1107 "long long" => "x",
1108 "__int64" => "x",
1109 "unsigned long long" => "y",
1110 "__int128" => "n",
1111 "unsigned __int128" => "o",
1112 "float" => "f",
1113 "double" => "d",
1114 "long double" => "e",
1115 "__float80" => "e",
1116 "__float128" => "g",
1117 "..." => "z"
1118);
1119
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001120my %IntrinsicNames = map {$_=>1} keys(%IntrinsicMangling);
1121
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001122my %StdcxxMangling = (
1123 "3std"=>"St",
1124 "3std9allocator"=>"Sa",
1125 "3std12basic_string"=>"Sb",
1126 "3std12basic_stringIcE"=>"Ss",
1127 "3std13basic_istreamIcE"=>"Si",
1128 "3std13basic_ostreamIcE"=>"So",
1129 "3std14basic_iostreamIcE"=>"Sd"
1130);
1131
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04001132my $DEFAULT_STD_PARMS = "std::(allocator|less|char_traits|regex_traits|istreambuf_iterator|ostreambuf_iterator)";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001133my %DEFAULT_STD_ARGS = map {$_=>1} ("_Alloc", "_Compare", "_Traits", "_Rx_traits", "_InIter", "_OutIter");
1134
1135my $ADD_TMPL_INSTANCES = 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001136my $EMERGENCY_MODE_48 = 0;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001137
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001138my %ConstantSuffix = (
1139 "unsigned int"=>"u",
1140 "long"=>"l",
1141 "unsigned long"=>"ul",
1142 "long long"=>"ll",
1143 "unsigned long long"=>"ull"
1144);
1145
1146my %ConstantSuffixR =
1147reverse(%ConstantSuffix);
1148
1149my %OperatorMangling = (
1150 "~" => "co",
1151 "=" => "aS",
1152 "|" => "or",
1153 "^" => "eo",
1154 "&" => "an",#ad (addr)
1155 "==" => "eq",
1156 "!" => "nt",
1157 "!=" => "ne",
1158 "<" => "lt",
1159 "<=" => "le",
1160 "<<" => "ls",
1161 "<<=" => "lS",
1162 ">" => "gt",
1163 ">=" => "ge",
1164 ">>" => "rs",
1165 ">>=" => "rS",
1166 "()" => "cl",
1167 "%" => "rm",
1168 "[]" => "ix",
1169 "&&" => "aa",
1170 "||" => "oo",
1171 "*" => "ml",#de (deref)
1172 "++" => "pp",#
1173 "--" => "mm",#
1174 "new" => "nw",
1175 "delete" => "dl",
1176 "new[]" => "na",
1177 "delete[]" => "da",
1178 "+=" => "pL",
1179 "+" => "pl",#ps (pos)
1180 "-" => "mi",#ng (neg)
1181 "-=" => "mI",
1182 "*=" => "mL",
1183 "/=" => "dV",
1184 "&=" => "aN",
1185 "|=" => "oR",
1186 "%=" => "rM",
1187 "^=" => "eO",
1188 "/" => "dv",
1189 "->*" => "pm",
1190 "->" => "pt",#rf (ref)
1191 "," => "cm",
1192 "?" => "qu",
1193 "." => "dt",
1194 "sizeof"=> "sz"#st
1195);
1196
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001197my %Intrinsic_Keywords = map {$_=>1} (
1198 "true",
1199 "false",
1200 "_Bool",
1201 "_Complex",
1202 "const",
1203 "int",
1204 "long",
1205 "void",
1206 "short",
1207 "float",
1208 "volatile",
1209 "restrict",
1210 "unsigned",
1211 "signed",
1212 "char",
1213 "double",
1214 "class",
1215 "struct",
1216 "union",
1217 "enum"
1218);
1219
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001220my %GlibcHeader = map {$_=>1} (
1221 "aliases.h",
1222 "argp.h",
1223 "argz.h",
1224 "assert.h",
1225 "cpio.h",
1226 "ctype.h",
1227 "dirent.h",
1228 "envz.h",
1229 "errno.h",
1230 "error.h",
1231 "execinfo.h",
1232 "fcntl.h",
1233 "fstab.h",
1234 "ftw.h",
1235 "glob.h",
1236 "grp.h",
1237 "iconv.h",
1238 "ifaddrs.h",
1239 "inttypes.h",
1240 "langinfo.h",
1241 "limits.h",
1242 "link.h",
1243 "locale.h",
1244 "malloc.h",
1245 "math.h",
1246 "mntent.h",
1247 "monetary.h",
1248 "nl_types.h",
1249 "obstack.h",
1250 "printf.h",
1251 "pwd.h",
1252 "regex.h",
1253 "sched.h",
1254 "search.h",
1255 "setjmp.h",
1256 "shadow.h",
1257 "signal.h",
1258 "spawn.h",
1259 "stdarg.h",
1260 "stdint.h",
1261 "stdio.h",
1262 "stdlib.h",
1263 "string.h",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001264 "strings.h",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001265 "tar.h",
1266 "termios.h",
1267 "time.h",
1268 "ulimit.h",
1269 "unistd.h",
1270 "utime.h",
1271 "wchar.h",
1272 "wctype.h",
1273 "wordexp.h" );
1274
1275my %GlibcDir = map {$_=>1} (
1276 "arpa",
1277 "bits",
1278 "gnu",
1279 "netinet",
1280 "net",
1281 "nfs",
1282 "rpc",
1283 "sys",
1284 "linux" );
1285
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001286my %WinHeaders = map {$_=>1} (
1287 "dos.h",
1288 "process.h",
1289 "winsock.h",
1290 "config-win.h",
1291 "mem.h",
1292 "windows.h",
1293 "winsock2.h",
1294 "crtdbg.h",
1295 "ws2tcpip.h"
1296);
1297
1298my %ObsoleteHeaders = map {$_=>1} (
1299 "iostream.h",
1300 "fstream.h"
1301);
1302
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001303my %AlienHeaders = map {$_=>1} (
1304 # Solaris
1305 "thread.h",
1306 "sys/atomic.h",
1307 # HPUX
1308 "sys/stream.h",
1309 # Symbian
1310 "AknDoc.h",
1311 # Atari ST
1312 "ext.h",
1313 "tos.h",
1314 # MS-DOS
1315 "alloc.h",
1316 # Sparc
1317 "sys/atomic.h"
1318);
1319
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001320my %ConfHeaders = map {$_=>1} (
1321 "atomic",
1322 "conf.h",
1323 "config.h",
1324 "configure.h",
1325 "build.h",
1326 "setup.h"
1327);
1328
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001329my %LocalIncludes = map {$_=>1} (
1330 "/usr/local/include",
1331 "/usr/local" );
1332
1333my %OS_AddPath=(
1334# These paths are needed if the tool cannot detect them automatically
1335 "macos"=>{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001336 "include"=>[
1337 "/Library",
1338 "/Developer/usr/include"
1339 ],
1340 "lib"=>[
1341 "/Library",
1342 "/Developer/usr/lib"
1343 ],
1344 "bin"=>[
1345 "/Developer/usr/bin"
1346 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001347 },
1348 "beos"=>{
1349 # Haiku has GCC 2.95.3 by default
1350 # try to find GCC>=3.0 in /boot/develop/abi
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001351 "include"=>[
1352 "/boot/common",
1353 "/boot/develop"
1354 ],
1355 "lib"=>[
1356 "/boot/common/lib",
1357 "/boot/system/lib",
1358 "/boot/apps"
1359 ],
1360 "bin"=>[
1361 "/boot/common/bin",
1362 "/boot/system/bin",
1363 "/boot/develop/abi"
1364 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001365 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001366);
1367
1368my %Slash_Type=(
1369 "default"=>"/",
1370 "windows"=>"\\"
1371);
1372
1373my $SLASH = $Slash_Type{$OSgroup}?$Slash_Type{$OSgroup}:$Slash_Type{"default"};
1374
1375# Global Variables
1376my %COMMON_LANGUAGE=(
1377 1 => "C",
1378 2 => "C" );
1379
1380my $MAX_COMMAND_LINE_ARGUMENTS = 4096;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001381my $MAX_CPPFILT_FILE_SIZE = 50000;
1382my $CPPFILT_SUPPORT_FILE;
1383
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001384my (%WORD_SIZE, %CPU_ARCH, %GCC_VERSION);
1385
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001386my $STDCXX_TESTING = 0;
1387my $GLIBC_TESTING = 0;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001388my $CPP_HEADERS = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001389
1390my $CheckHeadersOnly = $CheckHeadersOnly_Opt;
1391my $CheckObjectsOnly = $CheckObjectsOnly_Opt;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001392
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001393my $TargetComponent;
1394
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001395my $CheckUndefined = 0;
1396
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001397# Set Target Component Name
1398if($TargetComponent_Opt) {
1399 $TargetComponent = lc($TargetComponent_Opt);
1400}
1401else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001402{ # default: library
1403 # other components: header, system, ...
1404 $TargetComponent = "library";
1405}
1406
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001407my $TOP_REF = "<a style='font-size:11px;' href='#Top'>to the top</a>";
1408
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001409my $SystemRoot;
1410
1411my $MAIN_CPP_DIR;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001412my %RESULT;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001413my %LOG_PATH;
1414my %DEBUG_PATH;
1415my %Cache;
1416my %LibInfo;
1417my $COMPILE_ERRORS = 0;
1418my %CompilerOptions;
1419my %CheckedDyLib;
1420my $TargetLibraryShortName = parse_libname($TargetLibraryName, "shortest", $OSgroup);
1421
1422# Constants (#defines)
1423my %Constants;
1424my %SkipConstants;
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04001425my %EnumConstants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001426
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001427# Extra Info
1428my %SymbolHeader;
1429my %KnownLibs;
1430
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001431# Templates
1432my %TemplateInstance;
1433my %BasicTemplate;
1434my %TemplateArg;
1435my %TemplateDecl;
1436my %TemplateMap;
1437
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001438# Types
1439my %TypeInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001440my %SkipTypes = (
1441 "1"=>{},
1442 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001443my %CheckedTypes;
1444my %TName_Tid;
1445my %EnumMembName_Id;
1446my %NestedNameSpaces = (
1447 "1"=>{},
1448 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001449my %VirtualTable;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001450my %VirtualTable_Model;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001451my %ClassVTable;
1452my %ClassVTable_Content;
1453my %VTableClass;
1454my %AllocableClass;
1455my %ClassMethods;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001456my %ClassNames;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001457my %Class_SubClasses;
1458my %OverriddenMethods;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04001459my %TypedefToAnon;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001460my $MAX_ID = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001461
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001462my %CheckedTypeInfo;
1463
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001464# Typedefs
1465my %Typedef_BaseName;
1466my %Typedef_Tr;
1467my %Typedef_Eq;
1468my %StdCxxTypedef;
1469my %MissedTypedef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001470my %MissedBase;
1471my %MissedBase_R;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001472my %TypeTypedef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001473
1474# Symbols
1475my %SymbolInfo;
1476my %tr_name;
1477my %mangled_name_gcc;
1478my %mangled_name;
1479my %SkipSymbols = (
1480 "1"=>{},
1481 "2"=>{} );
1482my %SkipNameSpaces = (
1483 "1"=>{},
1484 "2"=>{} );
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001485my %AddNameSpaces = (
1486 "1"=>{},
1487 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001488my %SymbolsList;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001489my %SkipSymbolsList;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001490my %SymbolsList_App;
1491my %CheckedSymbols;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001492my %Symbol_Library = (
1493 "1"=>{},
1494 "2"=>{} );
1495my %Library_Symbol = (
1496 "1"=>{},
1497 "2"=>{} );
1498my %DepSymbol_Library = (
1499 "1"=>{},
1500 "2"=>{} );
1501my %DepLibrary_Symbol = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001502 "1"=>{},
1503 "2"=>{} );
1504my %MangledNames;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001505my %Func_ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001506my %AddIntParams;
1507my %Interface_Impl;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001508my %GlobalDataObject;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001509my %WeakSymbols;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001510my %Library_Needed= (
1511 "1"=>{},
1512 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001513
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001514# Extra Info
1515my %UndefinedSymbols;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001516my %PreprocessedHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001517
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001518# Headers
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001519my %Include_Preamble = (
1520 "1"=>[],
1521 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001522my %Registered_Headers;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001523my %Registered_Sources;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001524my %HeaderName_Paths;
1525my %Header_Dependency;
1526my %Include_Neighbors;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001527my %Include_Paths = (
1528 "1"=>[],
1529 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001530my %INC_PATH_AUTODETECT = (
1531 "1"=>1,
1532 "2"=>1 );
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001533my %Add_Include_Paths = (
1534 "1"=>[],
1535 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001536my %Skip_Include_Paths;
1537my %RegisteredDirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001538my %Header_ErrorRedirect;
1539my %Header_Includes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001540my %Header_Includes_R;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001541my %Header_ShouldNotBeUsed;
1542my %RecursiveIncludes;
1543my %Header_Include_Prefix;
1544my %SkipHeaders;
1545my %SkipHeadersList=(
1546 "1"=>{},
1547 "2"=>{} );
1548my %SkipLibs;
1549my %Include_Order;
1550my %TUnit_NameSpaces;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001551my %TUnit_Classes;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001552my %TUnit_Funcs;
1553my %TUnit_Vars;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001554
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001555my %CppMode = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001556 "1"=>0,
1557 "2"=>0 );
1558my %AutoPreambleMode = (
1559 "1"=>0,
1560 "2"=>0 );
1561my %MinGWMode = (
1562 "1"=>0,
1563 "2"=>0 );
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001564my %Cpp0xMode = (
1565 "1"=>0,
1566 "2"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001567
1568# Shared Objects
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001569my %RegisteredObjects;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001570my %RegisteredObjects_Short;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001571my %RegisteredSONAMEs;
1572my %RegisteredObject_Dirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001573
1574# System Objects
1575my %SystemObjects;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001576my @DefaultLibPaths;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001577my %DyLib_DefaultPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001578
1579# System Headers
1580my %SystemHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001581my @DefaultCppPaths;
1582my @DefaultGccPaths;
1583my @DefaultIncPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001584my %DefaultCppHeader;
1585my %DefaultGccHeader;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001586my @UsersIncPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001587
1588# Merging
1589my %CompleteSignature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001590my $Version;
1591my %AddedInt;
1592my %RemovedInt;
1593my %AddedInt_Virt;
1594my %RemovedInt_Virt;
1595my %VirtualReplacement;
1596my %ChangedTypedef;
1597my %CompatRules;
1598my %IncompleteRules;
1599my %UnknownRules;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001600my %VTableChanged_M;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001601my %ExtendedSymbols;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001602my %ReturnedClass;
1603my %ParamClass;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001604my %SourceAlternative;
1605my %SourceAlternative_B;
1606my %SourceReplacement;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001607my $CurrentSymbol; # for debugging
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001608
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001609# Calling Conventions
1610my %UseConv_Real = (
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001611 1=>{ "R"=>0, "P"=>0 },
1612 2=>{ "R"=>0, "P"=>0 }
1613);
1614
1615# ABI Dump
1616my %UsedDump;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001617
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001618# OS Compliance
1619my %TargetLibs;
1620my %TargetHeaders;
1621
1622# OS Specifics
1623my $OStarget = $OSgroup;
1624my %TargetTools;
1625
1626# Compliance Report
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001627my %Type_MaxSeverity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001628
1629# Recursion locks
1630my @RecurLib;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001631my @RecurTypes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001632my @RecurTypes_Diff;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001633my @RecurInclude;
1634my @RecurConstant;
1635
1636# System
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001637my %SystemPaths = (
1638 "include"=>[],
1639 "lib"=>[],
1640 "bin"=>[]
1641);
1642my @DefaultBinPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001643my $GCC_PATH;
1644
1645# Symbols versioning
1646my %SymVer = (
1647 "1"=>{},
1648 "2"=>{} );
1649
1650# Problem descriptions
1651my %CompatProblems;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001652my %CompatProblems_Constants;
1653my %CompatProblems_Impl;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001654my %TotalAffected;
1655
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001656# Reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001657my $ContentID = 1;
1658my $ContentSpanStart = "<span class=\"section\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1659my $ContentSpanStart_Affected = "<span class=\"section_affected\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1660my $ContentSpanStart_Info = "<span class=\"section_info\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1661my $ContentSpanEnd = "</span>\n";
1662my $ContentDivStart = "<div id=\"CONTENT_ID\" style=\"display:none;\">\n";
1663my $ContentDivEnd = "</div>\n";
1664my $Content_Counter = 0;
1665
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001666# Modes
1667my $JoinReport = 1;
1668my $DoubleReport = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001669
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04001670my %Severity_Val=(
1671 "High"=>3,
1672 "Medium"=>2,
1673 "Low"=>1,
1674 "Safe"=>-1
1675);
1676
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001677sub get_Modules()
1678{
1679 my $TOOL_DIR = get_dirname($0);
1680 if(not $TOOL_DIR)
1681 { # patch for MS Windows
1682 $TOOL_DIR = ".";
1683 }
1684 my @SEARCH_DIRS = (
1685 # tool's directory
1686 abs_path($TOOL_DIR),
1687 # relative path to modules
1688 abs_path($TOOL_DIR)."/../share/abi-compliance-checker",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001689 # install path
1690 'MODULES_INSTALL_PATH'
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001691 );
1692 foreach my $DIR (@SEARCH_DIRS)
1693 {
1694 if(not is_abs($DIR))
1695 { # relative path
1696 $DIR = abs_path($TOOL_DIR)."/".$DIR;
1697 }
1698 if(-d $DIR."/modules") {
1699 return $DIR."/modules";
1700 }
1701 }
1702 exitStatus("Module_Error", "can't find modules");
1703}
1704
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001705my %LoadedModules = ();
1706
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001707sub loadModule($)
1708{
1709 my $Name = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001710 if(defined $LoadedModules{$Name}) {
1711 return;
1712 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001713 my $Path = $MODULES_DIR."/Internals/$Name.pm";
1714 if(not -f $Path) {
1715 exitStatus("Module_Error", "can't access \'$Path\'");
1716 }
1717 require $Path;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001718 $LoadedModules{$Name} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001719}
1720
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001721sub readModule($$)
1722{
1723 my ($Module, $Name) = @_;
1724 my $Path = $MODULES_DIR."/Internals/$Module/".$Name;
1725 if(not -f $Path) {
1726 exitStatus("Module_Error", "can't access \'$Path\'");
1727 }
1728 return readFile($Path);
1729}
1730
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04001731sub showPos($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001732{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001733 my $Number = $_[0];
1734 if(not $Number) {
1735 $Number = 1;
1736 }
1737 else {
1738 $Number = int($Number)+1;
1739 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001740 if($Number>3) {
1741 return $Number."th";
1742 }
1743 elsif($Number==1) {
1744 return "1st";
1745 }
1746 elsif($Number==2) {
1747 return "2nd";
1748 }
1749 elsif($Number==3) {
1750 return "3rd";
1751 }
1752 else {
1753 return $Number;
1754 }
1755}
1756
1757sub search_Tools($)
1758{
1759 my $Name = $_[0];
1760 return "" if(not $Name);
1761 if(my @Paths = keys(%TargetTools))
1762 {
1763 foreach my $Path (@Paths)
1764 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001765 if(-f join_P($Path, $Name)) {
1766 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001767 }
1768 if($CrossPrefix)
1769 { # user-defined prefix (arm-none-symbianelf, ...)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001770 my $Candidate = join_P($Path, $CrossPrefix."-".$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001771 if(-f $Candidate) {
1772 return $Candidate;
1773 }
1774 }
1775 }
1776 }
1777 else {
1778 return "";
1779 }
1780}
1781
1782sub synch_Cmd($)
1783{
1784 my $Name = $_[0];
1785 if(not $GCC_PATH)
1786 { # GCC was not found yet
1787 return "";
1788 }
1789 my $Candidate = $GCC_PATH;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001790 if($Candidate=~s/\bgcc(|\.\w+)\Z/$Name$1/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001791 return $Candidate;
1792 }
1793 return "";
1794}
1795
1796sub get_CmdPath($)
1797{
1798 my $Name = $_[0];
1799 return "" if(not $Name);
1800 if(defined $Cache{"get_CmdPath"}{$Name}) {
1801 return $Cache{"get_CmdPath"}{$Name};
1802 }
1803 my %BinUtils = map {$_=>1} (
1804 "c++filt",
1805 "objdump",
1806 "readelf"
1807 );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001808 if($BinUtils{$Name} and $GCC_PATH)
1809 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001810 if(my $Dir = get_dirname($GCC_PATH)) {
1811 $TargetTools{$Dir}=1;
1812 }
1813 }
1814 my $Path = search_Tools($Name);
1815 if(not $Path and $OSgroup eq "windows") {
1816 $Path = search_Tools($Name.".exe");
1817 }
1818 if(not $Path and $BinUtils{$Name})
1819 {
1820 if($CrossPrefix)
1821 { # user-defined prefix
1822 $Path = search_Cmd($CrossPrefix."-".$Name);
1823 }
1824 }
1825 if(not $Path and $BinUtils{$Name})
1826 {
1827 if(my $Candidate = synch_Cmd($Name))
1828 { # synch with GCC
1829 if($Candidate=~/[\/\\]/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001830 { # command path
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001831 if(-f $Candidate) {
1832 $Path = $Candidate;
1833 }
1834 }
1835 elsif($Candidate = search_Cmd($Candidate))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001836 { # command name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001837 $Path = $Candidate;
1838 }
1839 }
1840 }
1841 if(not $Path) {
1842 $Path = search_Cmd($Name);
1843 }
1844 if(not $Path and $OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001845 { # search for *.exe file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001846 $Path=search_Cmd($Name.".exe");
1847 }
1848 if($Path=~/\s/) {
1849 $Path = "\"".$Path."\"";
1850 }
1851 return ($Cache{"get_CmdPath"}{$Name}=$Path);
1852}
1853
1854sub search_Cmd($)
1855{
1856 my $Name = $_[0];
1857 return "" if(not $Name);
1858 if(defined $Cache{"search_Cmd"}{$Name}) {
1859 return $Cache{"search_Cmd"}{$Name};
1860 }
1861 if(my $DefaultPath = get_CmdPath_Default($Name)) {
1862 return ($Cache{"search_Cmd"}{$Name} = $DefaultPath);
1863 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001864 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001865 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001866 my $CmdPath = join_P($Path,$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001867 if(-f $CmdPath)
1868 {
1869 if($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001870 next if(not check_gcc($CmdPath, "3"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001871 }
1872 return ($Cache{"search_Cmd"}{$Name} = $CmdPath);
1873 }
1874 }
1875 return ($Cache{"search_Cmd"}{$Name} = "");
1876}
1877
1878sub get_CmdPath_Default($)
1879{ # search in PATH
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001880 return "" if(not $_[0]);
1881 if(defined $Cache{"get_CmdPath_Default"}{$_[0]}) {
1882 return $Cache{"get_CmdPath_Default"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001883 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001884 return ($Cache{"get_CmdPath_Default"}{$_[0]} = get_CmdPath_Default_I($_[0]));
1885}
1886
1887sub get_CmdPath_Default_I($)
1888{ # search in PATH
1889 my $Name = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001890 if($Name=~/find/)
1891 { # special case: search for "find" utility
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001892 if(`find \"$TMP_DIR\" -maxdepth 0 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001893 return "find";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001894 }
1895 }
1896 elsif($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001897 return check_gcc($Name, "3");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001898 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001899 if(checkCmd($Name)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001900 return $Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001901 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001902 if($OSgroup eq "windows")
1903 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001904 if(`$Name /? 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001905 return $Name;
1906 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001907 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001908 foreach my $Path (@DefaultBinPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001909 {
1910 if(-f $Path."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001911 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001912 }
1913 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001914 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001915}
1916
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001917sub classifyPath($)
1918{
1919 my $Path = $_[0];
1920 if($Path=~/[\*\[]/)
1921 { # wildcard
1922 $Path=~s/\*/.*/g;
1923 $Path=~s/\\/\\\\/g;
1924 return ($Path, "Pattern");
1925 }
1926 elsif($Path=~/[\/\\]/)
1927 { # directory or relative path
1928 return (path_format($Path, $OSgroup), "Path");
1929 }
1930 else {
1931 return ($Path, "Name");
1932 }
1933}
1934
1935sub readDescriptor($$)
1936{
1937 my ($LibVersion, $Content) = @_;
1938 return if(not $LibVersion);
1939 my $DName = $DumpAPI?"descriptor":"descriptor \"d$LibVersion\"";
1940 if(not $Content) {
1941 exitStatus("Error", "$DName is empty");
1942 }
1943 if($Content!~/\</) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04001944 exitStatus("Error", "incorrect descriptor (see -d1 option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001945 }
1946 $Content=~s/\/\*(.|\n)+?\*\///g;
1947 $Content=~s/<\!--(.|\n)+?-->//g;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001948
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001949 $Descriptor{$LibVersion}{"Version"} = parseTag(\$Content, "version");
1950 if($TargetVersion{$LibVersion}) {
1951 $Descriptor{$LibVersion}{"Version"} = $TargetVersion{$LibVersion};
1952 }
1953 if(not $Descriptor{$LibVersion}{"Version"}) {
1954 exitStatus("Error", "version in the $DName is not specified (<version> section)");
1955 }
1956 if($Content=~/{RELPATH}/)
1957 {
1958 if(my $RelDir = $RelativeDirectory{$LibVersion}) {
1959 $Content =~ s/{RELPATH}/$RelDir/g;
1960 }
1961 else
1962 {
1963 my $NeedRelpath = $DumpAPI?"-relpath":"-relpath$LibVersion";
1964 exitStatus("Error", "you have not specified $NeedRelpath option, but the $DName contains {RELPATH} macro");
1965 }
1966 }
1967
1968 if(not $CheckObjectsOnly_Opt)
1969 {
1970 my $DHeaders = parseTag(\$Content, "headers");
1971 if(not $DHeaders) {
1972 exitStatus("Error", "header files in the $DName are not specified (<headers> section)");
1973 }
1974 elsif(lc($DHeaders) ne "none")
1975 { # append the descriptor headers list
1976 if($Descriptor{$LibVersion}{"Headers"})
1977 { # multiple descriptors
1978 $Descriptor{$LibVersion}{"Headers"} .= "\n".$DHeaders;
1979 }
1980 else {
1981 $Descriptor{$LibVersion}{"Headers"} = $DHeaders;
1982 }
1983 foreach my $Path (split(/\s*\n\s*/, $DHeaders))
1984 {
1985 if(not -e $Path) {
1986 exitStatus("Access_Error", "can't access \'$Path\'");
1987 }
1988 }
1989 }
1990 }
1991 if(not $CheckHeadersOnly_Opt)
1992 {
1993 my $DObjects = parseTag(\$Content, "libs");
1994 if(not $DObjects) {
1995 exitStatus("Error", "$SLIB_TYPE libraries in the $DName are not specified (<libs> section)");
1996 }
1997 elsif(lc($DObjects) ne "none")
1998 { # append the descriptor libraries list
1999 if($Descriptor{$LibVersion}{"Libs"})
2000 { # multiple descriptors
2001 $Descriptor{$LibVersion}{"Libs"} .= "\n".$DObjects;
2002 }
2003 else {
2004 $Descriptor{$LibVersion}{"Libs"} .= $DObjects;
2005 }
2006 foreach my $Path (split(/\s*\n\s*/, $DObjects))
2007 {
2008 if(not -e $Path) {
2009 exitStatus("Access_Error", "can't access \'$Path\'");
2010 }
2011 }
2012 }
2013 }
2014 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers")))
2015 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002016 if(not -d $Path) {
2017 exitStatus("Access_Error", "can't access directory \'$Path\'");
2018 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002019 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002020 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002021 push_U($SystemPaths{"include"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002022 }
2023 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs")))
2024 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002025 if(not -d $Path) {
2026 exitStatus("Access_Error", "can't access directory \'$Path\'");
2027 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002028 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002029 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002030 push_U($SystemPaths{"lib"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002031 }
2032 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools")))
2033 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002034 if(not -d $Path) {
2035 exitStatus("Access_Error", "can't access directory \'$Path\'");
2036 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002037 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002038 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002039 push_U($SystemPaths{"bin"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002040 $TargetTools{$Path}=1;
2041 }
2042 if(my $Prefix = parseTag(\$Content, "cross_prefix")) {
2043 $CrossPrefix = $Prefix;
2044 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002045 $Descriptor{$LibVersion}{"IncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"IncludePaths"}); # perl 5.8 doesn't support //=
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002046 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "include_paths")))
2047 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002048 if(not -d $Path) {
2049 exitStatus("Access_Error", "can't access directory \'$Path\'");
2050 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002051 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002052 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002053 push(@{$Descriptor{$LibVersion}{"IncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002054 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002055 $Descriptor{$LibVersion}{"AddIncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"AddIncludePaths"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002056 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "add_include_paths")))
2057 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002058 if(not -d $Path) {
2059 exitStatus("Access_Error", "can't access directory \'$Path\'");
2060 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002061 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002062 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002063 push(@{$Descriptor{$LibVersion}{"AddIncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002064 }
2065 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_include_paths")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002066 { # skip some auto-generated include paths
2067 if(not is_abs($Path))
2068 {
2069 if(my $P = abs_path($Path)) {
2070 $Path = $P;
2071 }
2072 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002073 $Skip_Include_Paths{$LibVersion}{path_format($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002074 }
2075 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_including")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002076 { # skip direct including of some headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002077 my ($CPath, $Type) = classifyPath($Path);
2078 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002079 }
2080 $Descriptor{$LibVersion}{"GccOptions"} = parseTag(\$Content, "gcc_options");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002081 foreach my $Option (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"GccOptions"}))
2082 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002083 if($Option!~/\A\-(Wl|l|L)/)
2084 { # skip linker options
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002085 $CompilerOptions{$LibVersion} .= " ".$Option;
2086 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002087 }
2088 $Descriptor{$LibVersion}{"SkipHeaders"} = parseTag(\$Content, "skip_headers");
2089 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipHeaders"}))
2090 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002091 $SkipHeadersList{$LibVersion}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002092 my ($CPath, $Type) = classifyPath($Path);
2093 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002094 }
2095 $Descriptor{$LibVersion}{"SkipLibs"} = parseTag(\$Content, "skip_libs");
2096 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipLibs"}))
2097 {
2098 my ($CPath, $Type) = classifyPath($Path);
2099 $SkipLibs{$LibVersion}{$Type}{$CPath} = 1;
2100 }
2101 if(my $DDefines = parseTag(\$Content, "defines"))
2102 {
2103 if($Descriptor{$LibVersion}{"Defines"})
2104 { # multiple descriptors
2105 $Descriptor{$LibVersion}{"Defines"} .= "\n".$DDefines;
2106 }
2107 else {
2108 $Descriptor{$LibVersion}{"Defines"} = $DDefines;
2109 }
2110 }
2111 foreach my $Order (split(/\s*\n\s*/, parseTag(\$Content, "include_order")))
2112 {
2113 if($Order=~/\A(.+):(.+)\Z/) {
2114 $Include_Order{$LibVersion}{$1} = $2;
2115 }
2116 }
2117 foreach my $Type_Name (split(/\s*\n\s*/, parseTag(\$Content, "opaque_types")),
2118 split(/\s*\n\s*/, parseTag(\$Content, "skip_types")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002119 { # opaque_types renamed to skip_types (1.23.4)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002120 $SkipTypes{$LibVersion}{$Type_Name} = 1;
2121 }
2122 foreach my $Symbol (split(/\s*\n\s*/, parseTag(\$Content, "skip_interfaces")),
2123 split(/\s*\n\s*/, parseTag(\$Content, "skip_symbols")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002124 { # skip_interfaces renamed to skip_symbols (1.22.1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002125 $SkipSymbols{$LibVersion}{$Symbol} = 1;
2126 }
2127 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "skip_namespaces"))) {
2128 $SkipNameSpaces{$LibVersion}{$NameSpace} = 1;
2129 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04002130 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "add_namespaces"))) {
2131 $AddNameSpaces{$LibVersion}{$NameSpace} = 1;
2132 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002133 foreach my $Constant (split(/\s*\n\s*/, parseTag(\$Content, "skip_constants"))) {
2134 $SkipConstants{$LibVersion}{$Constant} = 1;
2135 }
2136 if(my $DIncPreamble = parseTag(\$Content, "include_preamble"))
2137 {
2138 if($Descriptor{$LibVersion}{"IncludePreamble"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002139 { # multiple descriptors
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002140 $Descriptor{$LibVersion}{"IncludePreamble"} .= "\n".$DIncPreamble;
2141 }
2142 else {
2143 $Descriptor{$LibVersion}{"IncludePreamble"} = $DIncPreamble;
2144 }
2145 }
2146}
2147
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002148sub parseTag(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002149{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002150 my $CodeRef = shift(@_);
2151 my $Tag = shift(@_);
2152 if(not $Tag or not $CodeRef) {
2153 return undef;
2154 }
2155 my $Sp = 0;
2156 if(@_) {
2157 $Sp = shift(@_);
2158 }
2159 my $Start = index(${$CodeRef}, "<$Tag>");
2160 if($Start!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002161 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002162 my $End = index(${$CodeRef}, "</$Tag>");
2163 if($End!=-1)
2164 {
2165 my $TS = length($Tag)+3;
2166 my $Content = substr(${$CodeRef}, $Start, $End-$Start+$TS, "");
2167 substr($Content, 0, $TS-1, ""); # cut start tag
2168 substr($Content, -$TS, $TS, ""); # cut end tag
2169 if(not $Sp)
2170 {
2171 $Content=~s/\A\s+//g;
2172 $Content=~s/\s+\Z//g;
2173 }
2174 if(substr($Content, 0, 1) ne "<") {
2175 $Content = xmlSpecChars_R($Content);
2176 }
2177 return $Content;
2178 }
2179 }
2180 return undef;
2181}
2182
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002183sub getInfo($)
2184{
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002185 my $DumpPath = $_[0];
2186 return if(not $DumpPath or not -f $DumpPath);
2187
2188 readTUDump($DumpPath);
2189
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002190 # processing info
2191 setTemplateParams_All();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002192
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002193 if($ExtraDump) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002194 setAnonTypedef_All();
2195 }
2196
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002197 getTypeInfo_All();
2198 simplifyNames();
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002199 simplifyConstants();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002200 getVarInfo_All();
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002201 getSymbolInfo_All();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002202
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002203 # clean memory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002204 %LibInfo = ();
2205 %TemplateInstance = ();
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002206 %BasicTemplate = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002207 %MangledNames = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002208 %TemplateDecl = ();
2209 %StdCxxTypedef = ();
2210 %MissedTypedef = ();
2211 %Typedef_Tr = ();
2212 %Typedef_Eq = ();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002213 %TypedefToAnon = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002214
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002215 # clean cache
2216 delete($Cache{"getTypeAttr"});
2217 delete($Cache{"getTypeDeclId"});
2218
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002219 if($ExtraDump)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002220 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002221 remove_Unused($Version, "Extra");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002222 }
2223 else
2224 { # remove unused types
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002225 if($BinaryOnly and not $ExtendedCheck)
2226 { # --binary
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002227 remove_Unused($Version, "All");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002228 }
2229 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002230 remove_Unused($Version, "Extended");
2231 }
2232 }
2233
2234 if($CheckInfo)
2235 {
2236 foreach my $Tid (keys(%{$TypeInfo{$Version}})) {
2237 check_Completeness($TypeInfo{$Version}{$Tid}, $Version);
2238 }
2239
2240 foreach my $Sid (keys(%{$SymbolInfo{$Version}})) {
2241 check_Completeness($SymbolInfo{$Version}{$Sid}, $Version);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002242 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002243 }
2244
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002245 if($Debug) {
2246 # debugMangling($Version);
2247 }
2248}
2249
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002250sub readTUDump($)
2251{
2252 my $DumpPath = $_[0];
2253
2254 open(TU_DUMP, $DumpPath);
2255 local $/ = undef;
2256 my $Content = <TU_DUMP>;
2257 close(TU_DUMP);
2258
2259 unlink($DumpPath);
2260
2261 $Content=~s/\n[ ]+/ /g;
2262 my @Lines = split("\n", $Content);
2263
2264 # clean memory
2265 undef $Content;
2266
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002267 $MAX_ID = $#Lines+1; # number of lines == number of nodes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002268
2269 foreach (0 .. $#Lines)
2270 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002271 if($Lines[$_]=~/\A\@(\d+)[ ]+([a-z_]+)[ ]+(.+)\Z/i)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002272 { # get a number and attributes of a node
2273 next if(not $NodeType{$2});
2274 $LibInfo{$Version}{"info_type"}{$1}=$2;
2275 $LibInfo{$Version}{"info"}{$1}=$3;
2276 }
2277
2278 # clean memory
2279 delete($Lines[$_]);
2280 }
2281
2282 # clean memory
2283 undef @Lines;
2284}
2285
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002286sub simplifyConstants()
2287{
2288 foreach my $Constant (keys(%{$Constants{$Version}}))
2289 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002290 if(defined $Constants{$Version}{$Constant}{"Header"})
2291 {
2292 my $Value = $Constants{$Version}{$Constant}{"Value"};
2293 if(defined $EnumConstants{$Version}{$Value}) {
2294 $Constants{$Version}{$Constant}{"Value"} = $EnumConstants{$Version}{$Value}{"Value"};
2295 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002296 }
2297 }
2298}
2299
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002300sub simplifyNames()
2301{
2302 foreach my $Base (keys(%{$Typedef_Tr{$Version}}))
2303 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002304 if($Typedef_Eq{$Version}{$Base}) {
2305 next;
2306 }
2307 my @Translations = sort keys(%{$Typedef_Tr{$Version}{$Base}});
2308 if($#Translations==0)
2309 {
2310 if(length($Translations[0])<=length($Base)) {
2311 $Typedef_Eq{$Version}{$Base} = $Translations[0];
2312 }
2313 }
2314 else
2315 { # select most appropriate
2316 foreach my $Tr (@Translations)
2317 {
2318 if($Base=~/\A\Q$Tr\E/)
2319 {
2320 $Typedef_Eq{$Version}{$Base} = $Tr;
2321 last;
2322 }
2323 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002324 }
2325 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002326 foreach my $TypeId (keys(%{$TypeInfo{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002327 {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002328 my $TypeName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002329 if(not $TypeName) {
2330 next;
2331 }
2332 next if(index($TypeName,"<")==-1);# template instances only
2333 if($TypeName=~/>(::\w+)+\Z/)
2334 { # skip unused types
2335 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002336 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002337 foreach my $Base (sort {length($b)<=>length($a)}
2338 sort {$b cmp $a} keys(%{$Typedef_Eq{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002339 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002340 next if(not $Base);
2341 next if(index($TypeName,$Base)==-1);
2342 next if(length($TypeName) - length($Base) <= 3);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002343 if(my $Typedef = $Typedef_Eq{$Version}{$Base})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002344 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002345 $TypeName=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g;
2346 $TypeName=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g;
2347 if(defined $TypeInfo{$Version}{$TypeId}{"TParam"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002348 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002349 foreach my $TPos (keys(%{$TypeInfo{$Version}{$TypeId}{"TParam"}}))
2350 {
2351 if(my $TPName = $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"})
2352 {
2353 $TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g;
2354 $TPName=~s/\A\Q$Base\E(\w|\Z)/$Typedef $1/g;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002355 $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName, "T");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002356 }
2357 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002358 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002359 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002360 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002361 $TypeName = formatName($TypeName, "T");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002362 $TypeInfo{$Version}{$TypeId}{"Name"} = $TypeName;
2363 $TName_Tid{$Version}{$TypeName} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002364 }
2365}
2366
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002367sub setAnonTypedef_All()
2368{
2369 foreach my $InfoId (keys(%{$LibInfo{$Version}{"info"}}))
2370 {
2371 if($LibInfo{$Version}{"info_type"}{$InfoId} eq "type_decl")
2372 {
2373 if(isAnon(getNameByInfo($InfoId))) {
2374 $TypedefToAnon{getTypeId($InfoId)} = 1;
2375 }
2376 }
2377 }
2378}
2379
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002380sub setTemplateParams_All()
2381{
2382 foreach (keys(%{$LibInfo{$Version}{"info"}}))
2383 {
2384 if($LibInfo{$Version}{"info_type"}{$_} eq "template_decl") {
2385 setTemplateParams($_);
2386 }
2387 }
2388}
2389
2390sub setTemplateParams($)
2391{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002392 my $Tid = getTypeId($_[0]);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002393 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002394 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002395 if($Info=~/(inst|spcs)[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002396 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002397 my $TmplInst_Id = $2;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002398 setTemplateInstParams($_[0], $TmplInst_Id);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002399 while($TmplInst_Id = getNextElem($TmplInst_Id)) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002400 setTemplateInstParams($_[0], $TmplInst_Id);
2401 }
2402 }
2403
2404 $BasicTemplate{$Version}{$Tid} = $_[0];
2405
2406 if(my $Prms = getTreeAttr_Prms($_[0]))
2407 {
2408 if(my $Valu = getTreeAttr_Valu($Prms))
2409 {
2410 my $Vector = getTreeVec($Valu);
2411 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Vector}))
2412 {
2413 if(my $Val = getTreeAttr_Valu($Vector->{$Pos}))
2414 {
2415 if(my $Name = getNameByInfo($Val))
2416 {
2417 $TemplateArg{$Version}{$_[0]}{$Pos} = $Name;
2418 if($LibInfo{$Version}{"info_type"}{$Val} eq "parm_decl") {
2419 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = $Val;
2420 }
2421 else {
2422 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = getTreeAttr_Type($Val);
2423 }
2424 }
2425 }
2426 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002427 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002428 }
2429 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002430 if(my $TypeId = getTreeAttr_Type($_[0]))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002431 {
2432 if(my $IType = $LibInfo{$Version}{"info_type"}{$TypeId})
2433 {
2434 if($IType eq "record_type") {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002435 $TemplateDecl{$Version}{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002436 }
2437 }
2438 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002439}
2440
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002441sub setTemplateInstParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002442{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002443 my ($Tmpl, $Inst) = @_;
2444
2445 if(my $Info = $LibInfo{$Version}{"info"}{$Inst})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002446 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002447 my ($Params_InfoId, $ElemId) = ();
2448 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
2449 $Params_InfoId = $1;
2450 }
2451 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
2452 $ElemId = $1;
2453 }
2454 if($Params_InfoId and $ElemId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002455 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002456 my $Params_Info = $LibInfo{$Version}{"info"}{$Params_InfoId};
2457 while($Params_Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
2458 {
2459 my ($PPos, $PTypeId) = ($1, $2);
2460 if(my $PType = $LibInfo{$Version}{"info_type"}{$PTypeId})
2461 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002462 if($PType eq "template_type_parm") {
2463 $TemplateDecl{$Version}{$ElemId} = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002464 }
2465 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002466 if($LibInfo{$Version}{"info_type"}{$ElemId} eq "function_decl")
2467 { # functions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002468 $TemplateInstance{$Version}{"Func"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002469 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002470 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002471 else
2472 { # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002473 $TemplateInstance{$Version}{"Type"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002474 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002475 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002476 }
2477 }
2478 }
2479}
2480
2481sub getTypeDeclId($)
2482{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002483 if($_[0])
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002484 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002485 if(defined $Cache{"getTypeDeclId"}{$Version}{$_[0]}) {
2486 return $Cache{"getTypeDeclId"}{$Version}{$_[0]};
2487 }
2488 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2489 {
2490 if($Info=~/name[ ]*:[ ]*@(\d+)/) {
2491 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = $1);
2492 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002493 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002494 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002495 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002496}
2497
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002498sub getTypeInfo_All()
2499{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002500 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002501 { # support for GCC < 4.5
2502 # missed typedefs: QStyle::State is typedef to QFlags<QStyle::StateFlag>
2503 # but QStyleOption.state is of type QFlags<QStyle::StateFlag> in the TU dump
2504 # FIXME: check GCC versions
2505 addMissedTypes_Pre();
2506 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002507
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002508 foreach (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002509 { # forward order only
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002510 my $IType = $LibInfo{$Version}{"info_type"}{$_};
2511 if($IType=~/_type\Z/ and $IType ne "function_type"
2512 and $IType ne "method_type") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002513 getTypeInfo("$_");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002514 }
2515 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002516
2517 # add "..." type
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002518 $TypeInfo{$Version}{"-1"} = {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002519 "Name" => "...",
2520 "Type" => "Intrinsic",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002521 "Tid" => "-1"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002522 };
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002523 $TName_Tid{$Version}{"..."} = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002524
2525 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002526 { # support for GCC < 4.5
2527 addMissedTypes_Post();
2528 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002529
2530 if($ADD_TMPL_INSTANCES)
2531 {
2532 # templates
2533 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}}))
2534 {
2535 if(defined $TemplateMap{$Version}{$Tid}
2536 and not defined $TypeInfo{$Version}{$Tid}{"Template"})
2537 {
2538 if(defined $TypeInfo{$Version}{$Tid}{"Memb"})
2539 {
2540 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Memb"}}))
2541 {
2542 if(my $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"})
2543 {
2544 if(my %MAttr = getTypeAttr($MembTypeId))
2545 {
2546 $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"algn"} = $MAttr{"Algn"};
2547 $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"} = instType($TemplateMap{$Version}{$Tid}, $MembTypeId, $Version);
2548 }
2549 }
2550 }
2551 }
2552 if(defined $TypeInfo{$Version}{$Tid}{"Base"})
2553 {
2554 foreach my $Bid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Base"}}))
2555 {
2556 my $NBid = instType($TemplateMap{$Version}{$Tid}, $Bid, $Version);
2557
2558 if($NBid ne $Bid)
2559 {
2560 %{$TypeInfo{$Version}{$Tid}{"Base"}{$NBid}} = %{$TypeInfo{$Version}{$Tid}{"Base"}{$Bid}};
2561 delete($TypeInfo{$Version}{$Tid}{"Base"}{$Bid});
2562 }
2563 }
2564 }
2565 }
2566 }
2567 }
2568}
2569
2570sub createType($$)
2571{
2572 my ($Attr, $LibVersion) = @_;
2573 my $NewId = ++$MAX_ID;
2574
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04002575 $Attr->{"Tid"} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002576 $TypeInfo{$Version}{$NewId} = $Attr;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002577 $TName_Tid{$Version}{formatName($Attr->{"Name"}, "T")} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002578
2579 return "$NewId";
2580}
2581
2582sub instType($$$)
2583{ # create template instances
2584 my ($Map, $Tid, $LibVersion) = @_;
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002585
2586 if(not $TypeInfo{$LibVersion}{$Tid}) {
2587 return undef;
2588 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002589 my $Attr = dclone($TypeInfo{$LibVersion}{$Tid});
2590
2591 foreach my $Key (sort keys(%{$Map}))
2592 {
2593 if(my $Val = $Map->{$Key})
2594 {
2595 $Attr->{"Name"}=~s/\b$Key\b/$Val/g;
2596
2597 if(defined $Attr->{"NameSpace"}) {
2598 $Attr->{"NameSpace"}=~s/\b$Key\b/$Val/g;
2599 }
2600 foreach (keys(%{$Attr->{"TParam"}})) {
2601 $Attr->{"TParam"}{$_}{"name"}=~s/\b$Key\b/$Val/g;
2602 }
2603 }
2604 else
2605 { # remove absent
2606 # _Traits, etc.
2607 $Attr->{"Name"}=~s/,\s*\b$Key(,|>)/$1/g;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002608 if(defined $Attr->{"NameSpace"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002609 $Attr->{"NameSpace"}=~s/,\s*\b$Key(,|>)/$1/g;
2610 }
2611 foreach (keys(%{$Attr->{"TParam"}}))
2612 {
2613 if($Attr->{"TParam"}{$_}{"name"} eq $Key) {
2614 delete($Attr->{"TParam"}{$_});
2615 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002616 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002617 $Attr->{"TParam"}{$_}{"name"}=~s/,\s*\b$Key(,|>)/$1/g;
2618 }
2619 }
2620 }
2621 }
2622
2623 my $Tmpl = 0;
2624
2625 if(defined $Attr->{"TParam"})
2626 {
2627 foreach (sort {int($a)<=>int($b)} keys(%{$Attr->{"TParam"}}))
2628 {
2629 my $PName = $Attr->{"TParam"}{$_}{"name"};
2630
2631 if(my $PTid = $TName_Tid{$LibVersion}{$PName})
2632 {
2633 my %Base = get_BaseType($PTid, $LibVersion);
2634
2635 if($Base{"Type"} eq "TemplateParam"
2636 or defined $Base{"Template"})
2637 {
2638 $Tmpl = 1;
2639 last
2640 }
2641 }
2642 }
2643 }
2644
2645 if(my $Id = getTypeIdByName($Attr->{"Name"}, $LibVersion)) {
2646 return "$Id";
2647 }
2648 else
2649 {
2650 if(not $Tmpl) {
2651 delete($Attr->{"Template"});
2652 }
2653
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002654 my $New = createType($Attr, $LibVersion);
2655
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002656 my %EMap = ();
2657 if(defined $TemplateMap{$LibVersion}{$Tid}) {
2658 %EMap = %{$TemplateMap{$LibVersion}{$Tid}};
2659 }
2660 foreach (keys(%{$Map})) {
2661 $EMap{$_} = $Map->{$_};
2662 }
2663
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002664 if(defined $TypeInfo{$LibVersion}{$New}{"BaseType"}) {
2665 $TypeInfo{$LibVersion}{$New}{"BaseType"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"BaseType"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002666 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002667 if(defined $TypeInfo{$LibVersion}{$New}{"Base"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002668 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002669 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$New}{"Base"}}))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002670 {
2671 my $NBid = instType(\%EMap, $Bid, $LibVersion);
2672
2673 if($NBid ne $Bid)
2674 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002675 %{$TypeInfo{$LibVersion}{$New}{"Base"}{$NBid}} = %{$TypeInfo{$LibVersion}{$New}{"Base"}{$Bid}};
2676 delete($TypeInfo{$LibVersion}{$New}{"Base"}{$Bid});
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002677 }
2678 }
2679 }
2680
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002681 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002682 {
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002683 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Memb"}}))
2684 {
2685 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}) {
2686 $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}, $LibVersion);
2687 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002688 }
2689 }
2690
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002691 if(defined $TypeInfo{$LibVersion}{$New}{"Param"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002692 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002693 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Param"}})) {
2694 $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002695 }
2696 }
2697
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002698 if(defined $TypeInfo{$LibVersion}{$New}{"Return"}) {
2699 $TypeInfo{$LibVersion}{$New}{"Return"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Return"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002700 }
2701
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002702 return $New;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002703 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002704}
2705
2706sub addMissedTypes_Pre()
2707{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002708 my %MissedTypes = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002709 foreach my $MissedTDid (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
2710 { # detecting missed typedefs
2711 if($LibInfo{$Version}{"info_type"}{$MissedTDid} eq "type_decl")
2712 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002713 my $TypeId = getTreeAttr_Type($MissedTDid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002714 next if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002715 my $TypeType = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002716 if($TypeType eq "Unknown")
2717 { # template_type_parm
2718 next;
2719 }
2720 my $TypeDeclId = getTypeDeclId($TypeId);
2721 next if($TypeDeclId eq $MissedTDid);#or not $TypeDeclId
2722 my $TypedefName = getNameByInfo($MissedTDid);
2723 next if(not $TypedefName);
2724 next if($TypedefName eq "__float80");
2725 next if(isAnon($TypedefName));
2726 if(not $TypeDeclId
2727 or getNameByInfo($TypeDeclId) ne $TypedefName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002728 $MissedTypes{$Version}{$TypeId}{$MissedTDid} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002729 }
2730 }
2731 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002732 my %AddTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002733 foreach my $Tid (keys(%{$MissedTypes{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002734 { # add missed typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002735 my @Missed = keys(%{$MissedTypes{$Version}{$Tid}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002736 if(not @Missed or $#Missed>=1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002737 next;
2738 }
2739 my $MissedTDid = $Missed[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002740 my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002741 if(not $TypedefName) {
2742 next;
2743 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002744 my $NewId = ++$MAX_ID;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002745 my %MissedInfo = ( # typedef info
2746 "Name" => $TypedefName,
2747 "NameSpace" => $TypedefNS,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002748 "BaseType" => $Tid,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002749 "Type" => "Typedef",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002750 "Tid" => "$NewId" );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002751 my ($H, $L) = getLocation($MissedTDid);
2752 $MissedInfo{"Header"} = $H;
2753 $MissedInfo{"Line"} = $L;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002754 if($TypedefName=~/\*|\&|\s/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002755 { # other types
2756 next;
2757 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002758 if($TypedefName=~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002759 { # QFlags<Qt::DropAction>::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002760 next;
2761 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002762 if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002763 { # double-check for the name of typedef
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002764 my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002765 next if(not $TName);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002766 if(length($TypedefName)>=length($TName))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002767 { # too long typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002768 next;
2769 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002770 if($TName=~/\A\Q$TypedefName\E</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002771 next;
2772 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002773 if($TypedefName=~/\A\Q$TName\E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002774 { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002775 next;
2776 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002777 if(get_depth($TypedefName)==0 and get_depth($TName)!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002778 { # std::_Vector_base and std::vector::_Base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002779 next;
2780 }
2781 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002782
2783 $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo;
2784
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002785 # register typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002786 $MissedTypedef{$Version}{$Tid}{"Tid"} = $MissedInfo{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002787 $MissedTypedef{$Version}{$Tid}{"TDid"} = $MissedTDid;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002788 $TName_Tid{$Version}{$TypedefName} = $MissedInfo{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002789 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002790
2791 # add missed & remove other
2792 $TypeInfo{$Version} = \%AddTypes;
2793 delete($Cache{"getTypeAttr"}{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002794}
2795
2796sub addMissedTypes_Post()
2797{
2798 foreach my $BaseId (keys(%{$MissedTypedef{$Version}}))
2799 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002800 if(my $Tid = $MissedTypedef{$Version}{$BaseId}{"Tid"})
2801 {
2802 $TypeInfo{$Version}{$Tid}{"Size"} = $TypeInfo{$Version}{$BaseId}{"Size"};
2803 if(my $TName = $TypeInfo{$Version}{$Tid}{"Name"}) {
2804 $Typedef_BaseName{$Version}{$TName} = $TypeInfo{$Version}{$BaseId}{"Name"};
2805 }
2806 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002807 }
2808}
2809
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002810sub getTypeInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002811{
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002812 my $TypeId = $_[0];
2813 %{$TypeInfo{$Version}{$TypeId}} = getTypeAttr($TypeId);
2814 my $TName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002815 if(not $TName) {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002816 delete($TypeInfo{$Version}{$TypeId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002817 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002818}
2819
2820sub getArraySize($$)
2821{
2822 my ($TypeId, $BaseName) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002823 if(my $Size = getSize($TypeId))
2824 {
2825 my $Elems = $Size/$BYTE_SIZE;
2826 while($BaseName=~s/\s*\[(\d+)\]//) {
2827 $Elems/=$1;
2828 }
2829 if(my $BasicId = $TName_Tid{$Version}{$BaseName})
2830 {
2831 if(my $BasicSize = $TypeInfo{$Version}{$BasicId}{"Size"}) {
2832 $Elems/=$BasicSize;
2833 }
2834 }
2835 return $Elems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002836 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002837 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002838}
2839
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002840sub getTParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002841{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002842 my ($TypeId, $Kind) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002843 my @TmplParams = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002844 my @Positions = sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$Kind}{$TypeId}});
2845 foreach my $Pos (@Positions)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002846 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002847 my $Param_TypeId = $TemplateInstance{$Version}{$Kind}{$TypeId}{$Pos};
2848 my $NodeType = $LibInfo{$Version}{"info_type"}{$Param_TypeId};
2849 if(not $NodeType)
2850 { # typename_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002851 return ();
2852 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002853 if($NodeType eq "tree_vec")
2854 {
2855 if($Pos!=$#Positions)
2856 { # select last vector of parameters ( ns<P1>::type<P2> )
2857 next;
2858 }
2859 }
2860 my @Params = get_TemplateParam($Pos, $Param_TypeId);
2861 foreach my $P (@Params)
2862 {
2863 if($P eq "") {
2864 return ();
2865 }
2866 elsif($P ne "\@skip\@") {
2867 @TmplParams = (@TmplParams, $P);
2868 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002869 }
2870 }
2871 return @TmplParams;
2872}
2873
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002874sub getTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002875{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002876 my $TypeId = $_[0];
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002877 my %TypeAttr = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002878 if(defined $TypeInfo{$Version}{$TypeId}
2879 and $TypeInfo{$Version}{$TypeId}{"Name"})
2880 { # already created
2881 return %{$TypeInfo{$Version}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002882 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002883 elsif($Cache{"getTypeAttr"}{$Version}{$TypeId})
2884 { # incomplete type
2885 return ();
2886 }
2887 $Cache{"getTypeAttr"}{$Version}{$TypeId} = 1;
2888
2889 my $TypeDeclId = getTypeDeclId($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002890 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002891
2892 if(not $MissedBase{$Version}{$TypeId} and isTypedef($TypeId))
2893 {
2894 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
2895 {
2896 if($Info=~/qual[ ]*:/)
2897 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002898 my $NewId = ++$MAX_ID;
2899
2900 $MissedBase{$Version}{$TypeId} = "$NewId";
2901 $MissedBase_R{$Version}{$NewId} = $TypeId;
2902 $LibInfo{$Version}{"info"}{$NewId} = $LibInfo{$Version}{"info"}{$TypeId};
2903 $LibInfo{$Version}{"info_type"}{$NewId} = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002904 }
2905 }
2906 $TypeAttr{"Type"} = "Typedef";
2907 }
2908 else {
2909 $TypeAttr{"Type"} = getTypeType($TypeId);
2910 }
2911
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002912 if(my $ScopeId = getTreeAttr_Scpe($TypeDeclId))
2913 {
2914 if($LibInfo{$Version}{"info_type"}{$ScopeId} eq "function_decl")
2915 { # local code
2916 return ();
2917 }
2918 }
2919
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002920 if($TypeAttr{"Type"} eq "Unknown") {
2921 return ();
2922 }
2923 elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/)
2924 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002925 %TypeAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"});
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002926 if(my $TName = $TypeAttr{"Name"})
2927 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002928 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002929 $TName_Tid{$Version}{$TName} = $TypeId;
2930 return %TypeAttr;
2931 }
2932 else {
2933 return ();
2934 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002935 }
2936 elsif($TypeAttr{"Type"} eq "Array")
2937 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002938 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2939 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002940 return ();
2941 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002942 if(my $Algn = getAlgn($TypeId)) {
2943 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2944 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002945 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002946 if(my %BTAttr = getTypeAttr($BTid))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002947 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002948 if(not $BTAttr{"Name"}) {
2949 return ();
2950 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002951 if(my $NElems = getArraySize($TypeId, $BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002952 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002953 if(my $Size = getSize($TypeId)) {
2954 $TypeAttr{"Size"} = $Size/$BYTE_SIZE;
2955 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002956 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002957 $TypeAttr{"Name"} = $1."[$NElems]".$2;
2958 }
2959 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002960 $TypeAttr{"Name"} = $BTAttr{"Name"}."[$NElems]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002961 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002962 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002963 else
2964 {
2965 $TypeAttr{"Size"} = $WORD_SIZE{$Version}; # pointer
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002966 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002967 $TypeAttr{"Name"} = $1."[]".$2;
2968 }
2969 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002970 $TypeAttr{"Name"} = $BTAttr{"Name"}."[]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002971 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002972 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002973 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002974 if($BTAttr{"Header"}) {
2975 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002976 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002977 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002978 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2979 return %TypeAttr;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002980 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002981 return ();
2982 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002983 elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class|Vector)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002984 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002985 %TypeAttr = getTrivialTypeAttr($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002986 if($TypeAttr{"Name"})
2987 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002988 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002989
2990 if(not defined $IntrinsicNames{$TypeAttr{"Name"}}
2991 or getTypeDeclId($TypeAttr{"Tid"}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002992 { # NOTE: register only one int: with built-in decl
2993 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2994 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2995 }
2996 }
2997 return %TypeAttr;
2998 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002999 else {
3000 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003001 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003002 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003003 elsif($TypeAttr{"Type"}=~/TemplateParam|TypeName/)
3004 {
3005 %TypeAttr = getTrivialTypeAttr($TypeId);
3006 if($TypeAttr{"Name"})
3007 {
3008 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
3009 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3010 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3011 }
3012 return %TypeAttr;
3013 }
3014 else {
3015 return ();
3016 }
3017 }
3018 elsif($TypeAttr{"Type"} eq "SizeOf")
3019 {
3020 $TypeAttr{"BaseType"} = getTreeAttr_Type($TypeId);
3021 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
3022 $TypeAttr{"Name"} = "sizeof(".$BTAttr{"Name"}.")";
3023 if($TypeAttr{"Name"})
3024 {
3025 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
3026 return %TypeAttr;
3027 }
3028 else {
3029 return ();
3030 }
3031 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003032 else
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003033 { # derived types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003034 my ($BTid, $BTSpec) = selectBaseType($TypeId);
3035 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003036 return ();
3037 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003038 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003039 if(defined $MissedTypedef{$Version}{$BTid})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003040 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003041 if(my $MissedTDid = $MissedTypedef{$Version}{$BTid}{"TDid"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003042 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003043 if($MissedTDid ne $TypeDeclId) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003044 $TypeAttr{"BaseType"} = $MissedTypedef{$Version}{$BTid}{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003045 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003046 }
3047 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003048 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003049 if(not $BTAttr{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003050 { # templates
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003051 return ();
3052 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003053 if($BTAttr{"Type"} eq "Typedef")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003054 { # relinking typedefs
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003055 my %BaseBase = get_Type($BTAttr{"BaseType"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003056 if($BTAttr{"Name"} eq $BaseBase{"Name"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003057 $TypeAttr{"BaseType"} = $BaseBase{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003058 }
3059 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003060 if($BTSpec)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003061 {
3062 if($TypeAttr{"Type"} eq "Pointer"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003063 and $BTAttr{"Name"}=~/\([\*]+\)/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003064 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003065 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003066 $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g;
3067 }
3068 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003069 $TypeAttr{"Name"} = $BTAttr{"Name"}." ".$BTSpec;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003070 }
3071 }
3072 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003073 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003074 }
3075 if($TypeAttr{"Type"} eq "Typedef")
3076 {
3077 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003078
3079 if(index($TypeAttr{"Name"}, "tmp_add_type")==0) {
3080 return ();
3081 }
3082
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003083 if(isAnon($TypeAttr{"Name"}))
3084 { # anon typedef to anon type: ._N
3085 return ();
3086 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04003087
3088 if($LibInfo{$Version}{"info"}{$TypeDeclId}=~/ artificial /i)
3089 { # artificial typedef of "struct X" to "X"
3090 $TypeAttr{"Artificial"} = 1;
3091 }
3092
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003093 if(my $NS = getNameSpace($TypeDeclId))
3094 {
3095 my $TypeName = $TypeAttr{"Name"};
3096 if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/)
3097 { # "some_type" is the typedef to "struct some_type" in C++
3098 if($3) {
3099 $TypeAttr{"Name"} = $3."::".$TypeName;
3100 }
3101 }
3102 else
3103 {
3104 $TypeAttr{"NameSpace"} = $NS;
3105 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003106
3107 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/
3108 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/)
3109 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003110 if($BTAttr{"NameSpace"}
3111 and $BTAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr{"Name"}=~/</)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003112 { # types like "std::fpos<__mbstate_t>" are
3113 # not covered by typedefs in the TU dump
3114 # so trying to add such typedefs manually
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003115 $StdCxxTypedef{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
3116 if(length($TypeAttr{"Name"})<=length($BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003117 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003118 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003119 { # skip "other" in "std" and "type" in "boost"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003120 $Typedef_Eq{$Version}{$BTAttr{"Name"}} = $TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003121 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003122 }
3123 }
3124 }
3125 }
3126 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04003127 if($TypeAttr{"Name"} ne $BTAttr{"Name"} and not $TypeAttr{"Artificial"}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003128 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr{"Name"}!~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003129 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003130 if(not defined $Typedef_BaseName{$Version}{$TypeAttr{"Name"}})
3131 { # typedef int*const TYPEDEF; // first
3132 # int foo(TYPEDEF p); // const is optimized out
3133 $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BTAttr{"Name"};
3134 if($BTAttr{"Name"}=~/</)
3135 {
3136 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) {
3137 $Typedef_Tr{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
3138 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003139 }
3140 }
3141 }
3142 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId);
3143 }
3144 if(not $TypeAttr{"Size"})
3145 {
3146 if($TypeAttr{"Type"} eq "Pointer") {
3147 $TypeAttr{"Size"} = $WORD_SIZE{$Version};
3148 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003149 elsif($BTAttr{"Size"}) {
3150 $TypeAttr{"Size"} = $BTAttr{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003151 }
3152 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003153 if(my $Algn = getAlgn($TypeId)) {
3154 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3155 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003156 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003157 if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) {
3158 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003159 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003160 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003161 if($TypeAttr{"Name"} ne $BTAttr{"Name"})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003162 { # typedef to "class Class"
3163 # should not be registered in TName_Tid
3164 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3165 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3166 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003167 }
3168 return %TypeAttr;
3169 }
3170}
3171
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003172sub getTreeVec($)
3173{
3174 my %Vector = ();
3175 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3176 {
3177 while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
3178 { # string length is N-1 because of the null terminator
3179 $Vector{$1} = $2;
3180 }
3181 }
3182 return \%Vector;
3183}
3184
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003185sub get_TemplateParam($$)
3186{
3187 my ($Pos, $Type_Id) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003188 return () if(not $Type_Id);
3189 my $NodeType = $LibInfo{$Version}{"info_type"}{$Type_Id};
3190 return () if(not $NodeType);
3191 if($NodeType eq "integer_cst")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003192 { # int (1), unsigned (2u), char ('c' as 99), ...
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003193 my $CstTid = getTreeAttr_Type($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003194 my %CstType = getTypeAttr($CstTid); # without recursion
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003195 my $Num = getNodeIntCst($Type_Id);
3196 if(my $CstSuffix = $ConstantSuffix{$CstType{"Name"}}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003197 return ($Num.$CstSuffix);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003198 }
3199 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003200 return ("(".$CstType{"Name"}.")".$Num);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003201 }
3202 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003203 elsif($NodeType eq "string_cst") {
3204 return (getNodeStrCst($Type_Id));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003205 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003206 elsif($NodeType eq "tree_vec")
3207 {
3208 my $Vector = getTreeVec($Type_Id);
3209 my @Params = ();
3210 foreach my $P1 (sort {int($a)<=>int($b)} keys(%{$Vector}))
3211 {
3212 foreach my $P2 (get_TemplateParam($Pos, $Vector->{$P1})) {
3213 push(@Params, $P2);
3214 }
3215 }
3216 return @Params;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003217 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003218 elsif($NodeType eq "parm_decl")
3219 {
3220 (getNameByInfo($Type_Id));
3221 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003222 else
3223 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003224 my %ParamAttr = getTypeAttr($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003225 my $PName = $ParamAttr{"Name"};
3226 if(not $PName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003227 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003228 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003229 if($PName=~/\>/)
3230 {
3231 if(my $Cover = cover_stdcxx_typedef($PName)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003232 $PName = $Cover;
3233 }
3234 }
3235 if($Pos>=1 and
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04003236 $PName=~/\A$DEFAULT_STD_PARMS\</)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003237 { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
3238 # template<typename _Key, typename _Compare = std::less<_Key>
3239 # template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
3240 # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> >
3241 # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
3242 # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> >
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003243 return ("\@skip\@");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003244 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003245 return ($PName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003246 }
3247}
3248
3249sub cover_stdcxx_typedef($)
3250{
3251 my $TypeName = $_[0];
3252 if(my @Covers = sort {length($a)<=>length($b)}
3253 sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3254 { # take the shortest typedef
3255 # FIXME: there may be more than
3256 # one typedefs to the same type
3257 return $Covers[0];
3258 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003259 my $Covered = $TypeName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003260 while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){};
3261 if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3262 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003263 if(my $Cover = $Covers[0])
3264 {
3265 $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
3266 $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
3267 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003268 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003269 return formatName($Covered, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003270}
3271
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003272sub getNodeIntCst($)
3273{
3274 my $CstId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003275 my $CstTypeId = getTreeAttr_Type($CstId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003276 if($EnumMembName_Id{$Version}{$CstId}) {
3277 return $EnumMembName_Id{$Version}{$CstId};
3278 }
3279 elsif((my $Value = getTreeValue($CstId)) ne "")
3280 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003281 if($Value eq "0")
3282 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003283 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003284 return "false";
3285 }
3286 else {
3287 return "0";
3288 }
3289 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003290 elsif($Value eq "1")
3291 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003292 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003293 return "true";
3294 }
3295 else {
3296 return "1";
3297 }
3298 }
3299 else {
3300 return $Value;
3301 }
3302 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003303 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003304}
3305
3306sub getNodeStrCst($)
3307{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003308 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3309 {
3310 if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003311 {
3312 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "string_cst")
3313 { # string length is N-1 because of the null terminator
3314 return substr($1, 0, $2-1);
3315 }
3316 else
3317 { # identifier_node
3318 return substr($1, 0, $2);
3319 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003320 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003321 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003322 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003323}
3324
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003325sub getMemPtrAttr($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003326{ # function, method and field pointers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003327 my ($PtrId, $TypeId, $Type) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003328 my $MemInfo = $LibInfo{$Version}{"info"}{$PtrId};
3329 if($Type eq "FieldPtr") {
3330 $MemInfo = $LibInfo{$Version}{"info"}{$TypeId};
3331 }
3332 my $MemInfo_Type = $LibInfo{$Version}{"info_type"}{$PtrId};
3333 my $MemPtrName = "";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003334 my %TypeAttr = ("Size"=>$WORD_SIZE{$Version}, "Type"=>$Type, "Tid"=>$TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003335 if($Type eq "MethodPtr")
3336 { # size of "method pointer" may be greater than WORD size
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003337 if(my $Size = getSize($TypeId))
3338 {
3339 $Size/=$BYTE_SIZE;
3340 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003341 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003342 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003343 if(my $Algn = getAlgn($TypeId)) {
3344 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3345 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003346 # Return
3347 if($Type eq "FieldPtr")
3348 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003349 my %ReturnAttr = getTypeAttr($PtrId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003350 if($ReturnAttr{"Name"}) {
3351 $MemPtrName .= $ReturnAttr{"Name"};
3352 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003353 $TypeAttr{"Return"} = $PtrId;
3354 }
3355 else
3356 {
3357 if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /)
3358 {
3359 my $ReturnTypeId = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003360 my %ReturnAttr = getTypeAttr($ReturnTypeId);
3361 if(not $ReturnAttr{"Name"})
3362 { # templates
3363 return ();
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003364 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003365 $MemPtrName .= $ReturnAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003366 $TypeAttr{"Return"} = $ReturnTypeId;
3367 }
3368 }
3369 # Class
3370 if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /)
3371 {
3372 $TypeAttr{"Class"} = $2;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003373 my %Class = getTypeAttr($TypeAttr{"Class"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003374 if($Class{"Name"}) {
3375 $MemPtrName .= " (".$Class{"Name"}."\:\:*)";
3376 }
3377 else {
3378 $MemPtrName .= " (*)";
3379 }
3380 }
3381 else {
3382 $MemPtrName .= " (*)";
3383 }
3384 # Parameters
3385 if($Type eq "FuncPtr"
3386 or $Type eq "MethodPtr")
3387 {
3388 my @ParamTypeName = ();
3389 if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /)
3390 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003391 my $PTypeInfoId = $1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003392 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003393 while($PTypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003394 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003395 my $PTypeInfo = $LibInfo{$Version}{"info"}{$PTypeInfoId};
3396 if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003397 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003398 my $PTypeId = $1;
3399 my %ParamAttr = getTypeAttr($PTypeId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003400 if(not $ParamAttr{"Name"})
3401 { # templates (template_type_parm), etc.
3402 return ();
3403 }
3404 if($ParamAttr{"Name"} eq "void") {
3405 last;
3406 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003407 if($Pos!=0 or $Type ne "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003408 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003409 $TypeAttr{"Param"}{$PPos++}{"type"} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003410 push(@ParamTypeName, $ParamAttr{"Name"});
3411 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003412 if($PTypeInfoId = getNextElem($PTypeInfoId)) {
3413 $Pos+=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003414 }
3415 else {
3416 last;
3417 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003418 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003419 else {
3420 last;
3421 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003422 }
3423 }
3424 $MemPtrName .= " (".join(", ", @ParamTypeName).")";
3425 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003426 $TypeAttr{"Name"} = formatName($MemPtrName, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003427 return %TypeAttr;
3428}
3429
3430sub getTreeTypeName($)
3431{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003432 my $TypeId = $_[0];
3433 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003434 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003435 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "integer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003436 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003437 if(my $Name = getNameByInfo($TypeId))
3438 { # bit_size_type
3439 return $Name;
3440 }
3441 elsif($Info=~/unsigned/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003442 return "unsigned int";
3443 }
3444 else {
3445 return "int";
3446 }
3447 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003448 elsif($Info=~/name[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003449 return getNameByInfo($1);
3450 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003451 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003452 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003453}
3454
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003455sub isFuncPtr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003456{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003457 my $Ptd = pointTo($_[0]);
3458 return 0 if(not $Ptd);
3459 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003460 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003461 if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) {
3462 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003463 }
3464 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003465 if(my $InfoT1 = $LibInfo{$Version}{"info_type"}{$_[0]}
3466 and my $InfoT2 = $LibInfo{$Version}{"info_type"}{$Ptd})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003467 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003468 if($InfoT1 eq "pointer_type"
3469 and $InfoT2 eq "function_type") {
3470 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003471 }
3472 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003473 return 0;
3474}
3475
3476sub isMethodPtr($)
3477{
3478 my $Ptd = pointTo($_[0]);
3479 return 0 if(not $Ptd);
3480 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3481 {
3482 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "record_type"
3483 and $LibInfo{$Version}{"info_type"}{$Ptd} eq "method_type"
3484 and $Info=~/ ptrmem /) {
3485 return 1;
3486 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003487 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003488 return 0;
3489}
3490
3491sub isFieldPtr($)
3492{
3493 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3494 {
3495 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "offset_type"
3496 and $Info=~/ ptrmem /) {
3497 return 1;
3498 }
3499 }
3500 return 0;
3501}
3502
3503sub pointTo($)
3504{
3505 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3506 {
3507 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) {
3508 return $1;
3509 }
3510 }
3511 return "";
3512}
3513
3514sub getTypeTypeByTypeId($)
3515{
3516 my $TypeId = $_[0];
3517 if(my $TType = $LibInfo{$Version}{"info_type"}{$TypeId})
3518 {
3519 my $NType = $NodeType{$TType};
3520 if($NType eq "Intrinsic") {
3521 return $NType;
3522 }
3523 elsif(isFuncPtr($TypeId)) {
3524 return "FuncPtr";
3525 }
3526 elsif(isMethodPtr($TypeId)) {
3527 return "MethodPtr";
3528 }
3529 elsif(isFieldPtr($TypeId)) {
3530 return "FieldPtr";
3531 }
3532 elsif($NType ne "Other") {
3533 return $NType;
3534 }
3535 }
3536 return "Unknown";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003537}
3538
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003539my %UnQual = (
3540 "r"=>"restrict",
3541 "v"=>"volatile",
3542 "c"=>"const",
3543 "cv"=>"const volatile"
3544);
3545
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003546sub getQual($)
3547{
3548 my $TypeId = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003549 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
3550 {
3551 my ($Qual, $To) = ();
3552 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) {
3553 $Qual = $UnQual{$1};
3554 }
3555 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) {
3556 $To = $1;
3557 }
3558 if($Qual and $To) {
3559 return ($Qual, $To);
3560 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003561 }
3562 return ();
3563}
3564
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003565sub getQualType($)
3566{
3567 if($_[0] eq "const volatile") {
3568 return "ConstVolatile";
3569 }
3570 return ucfirst($_[0]);
3571}
3572
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003573sub getTypeType($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003574{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003575 my $TypeId = $_[0];
3576 my $TypeDeclId = getTypeDeclId($TypeId);
3577 if(defined $MissedTypedef{$Version}{$TypeId})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003578 { # support for old GCC versions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003579 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq $TypeDeclId) {
3580 return "Typedef";
3581 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003582 }
3583 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3584 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003585 if(($Qual or $To) and $TypeDeclId
3586 and (getTypeId($TypeDeclId) ne $TypeId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003587 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003588 return getQualType($Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003589 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003590 elsif(not $MissedBase_R{$Version}{$TypeId}
3591 and isTypedef($TypeId)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003592 return "Typedef";
3593 }
3594 elsif($Qual)
3595 { # qualified types
3596 return getQualType($Qual);
3597 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003598
3599 if($Info=~/unql[ ]*:[ ]*\@(\d+)/)
3600 { # typedef struct { ... } name
3601 $TypeTypedef{$Version}{$TypeId} = $1;
3602 }
3603
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003604 my $TypeType = getTypeTypeByTypeId($TypeId);
3605 if($TypeType eq "Struct")
3606 {
3607 if($TypeDeclId
3608 and $LibInfo{$Version}{"info_type"}{$TypeDeclId} eq "template_decl") {
3609 return "Template";
3610 }
3611 }
3612 return $TypeType;
3613}
3614
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003615sub isTypedef($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003616{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003617 if($_[0])
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003618 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003619 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "vector_type")
3620 { # typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16)));
3621 return 0;
3622 }
3623 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3624 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003625 if(my $TDid = getTypeDeclId($_[0]))
3626 {
3627 if(getTypeId($TDid) eq $_[0]
3628 and getNameByInfo($TDid))
3629 {
3630 if($Info=~/unql[ ]*:[ ]*\@(\d+) /) {
3631 return $1;
3632 }
3633 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003634 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003635 }
3636 }
3637 return 0;
3638}
3639
3640sub selectBaseType($)
3641{
3642 my $TypeId = $_[0];
3643 if(defined $MissedTypedef{$Version}{$TypeId})
3644 { # add missed typedefs
3645 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) {
3646 return ($TypeId, "");
3647 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003648 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003649 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3650 my $InfoType = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003651
3652 my $MB_R = $MissedBase_R{$Version}{$TypeId};
3653 my $MB = $MissedBase{$Version}{$TypeId};
3654
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003655 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003656 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) /
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003657 and (getTypeId($1) ne $TypeId)
3658 and (not $MB_R or getTypeId($1) ne $MB_R))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003659 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003660 return (getTypeId($1), $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003661 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003662 elsif($MB)
3663 { # add base
3664 return ($MB, "");
3665 }
3666 elsif(not $MB_R and my $Bid = isTypedef($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003667 { # typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003668 return ($Bid, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003669 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003670 elsif($Qual or $To)
3671 { # qualified types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003672 return ($To, $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003673 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003674 elsif($InfoType eq "reference_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003675 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003676 if($Info=~/refd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003677 return ($1, "&");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003678 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003679 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003680 elsif($InfoType eq "array_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003681 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003682 if($Info=~/elts[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003683 return ($1, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003684 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003685 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003686 elsif($InfoType eq "pointer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003687 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003688 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003689 return ($1, "*");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003690 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003691 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003692
3693 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003694}
3695
3696sub getSymbolInfo_All()
3697{
3698 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3699 { # reverse order
3700 if($LibInfo{$Version}{"info_type"}{$_} eq "function_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003701 getSymbolInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003702 }
3703 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003704
3705 if($ADD_TMPL_INSTANCES)
3706 {
3707 # templates
3708 foreach my $Sid (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$Version}}))
3709 {
3710 my %Map = ();
3711
3712 if(my $ClassId = $SymbolInfo{$Version}{$Sid}{"Class"})
3713 {
3714 if(defined $TemplateMap{$Version}{$ClassId})
3715 {
3716 foreach (keys(%{$TemplateMap{$Version}{$ClassId}})) {
3717 $Map{$_} = $TemplateMap{$Version}{$ClassId}{$_};
3718 }
3719 }
3720 }
3721
3722 if(defined $TemplateMap{$Version}{$Sid})
3723 {
3724 foreach (keys(%{$TemplateMap{$Version}{$Sid}})) {
3725 $Map{$_} = $TemplateMap{$Version}{$Sid}{$_};
3726 }
3727 }
3728
3729 if(defined $SymbolInfo{$Version}{$Sid}{"Param"})
3730 {
3731 foreach (keys(%{$SymbolInfo{$Version}{$Sid}{"Param"}}))
3732 {
3733 my $PTid = $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"};
3734 $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"} = instType(\%Map, $PTid, $Version);
3735 }
3736 }
3737 if(my $Return = $SymbolInfo{$Version}{$Sid}{"Return"}) {
3738 $SymbolInfo{$Version}{$Sid}{"Return"} = instType(\%Map, $Return, $Version);
3739 }
3740 }
3741 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003742}
3743
3744sub getVarInfo_All()
3745{
3746 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3747 { # reverse order
3748 if($LibInfo{$Version}{"info_type"}{$_} eq "var_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003749 getVarInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003750 }
3751 }
3752}
3753
3754sub isBuiltIn($) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003755 return ($_[0] and $_[0]=~/\<built\-in\>|\<internal\>|\A\./);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003756}
3757
3758sub getVarInfo($)
3759{
3760 my $InfoId = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003761 if(my $NSid = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003762 {
3763 my $NSInfoType = $LibInfo{$Version}{"info_type"}{$NSid};
3764 if($NSInfoType and $NSInfoType eq "function_decl") {
3765 return;
3766 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003767 }
3768 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
3769 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
3770 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) {
3771 delete($SymbolInfo{$Version}{$InfoId});
3772 return;
3773 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003774 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId));
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003775 if(not $ShortName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003776 delete($SymbolInfo{$Version}{$InfoId});
3777 return;
3778 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003779 if($ShortName=~/\Atmp_add_class_\d+\Z/) {
3780 delete($SymbolInfo{$Version}{$InfoId});
3781 return;
3782 }
3783 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003784 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
3785 {
3786 if($OSgroup eq "windows")
3787 { # cut the offset
3788 $MnglName=~s/\@\d+\Z//g;
3789 }
3790 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
3791 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003792 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003793 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003794 { # validate mangled name
3795 delete($SymbolInfo{$Version}{$InfoId});
3796 return;
3797 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003798 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003799 and index($ShortName, "_Z")==0)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003800 { # _ZTS, etc.
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003801 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003802 }
3803 if(isPrivateData($SymbolInfo{$Version}{$InfoId}{"MnglName"}))
3804 { # non-public global data
3805 delete($SymbolInfo{$Version}{$InfoId});
3806 return;
3807 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003808 $SymbolInfo{$Version}{$InfoId}{"Data"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003809 if(my $Rid = getTypeId($InfoId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003810 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003811 if(not defined $TypeInfo{$Version}{$Rid}
3812 or not $TypeInfo{$Version}{$Rid}{"Name"})
3813 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003814 delete($SymbolInfo{$Version}{$InfoId});
3815 return;
3816 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003817 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Rid;
3818 my $Val = getDataVal($InfoId, $Rid);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003819 if(defined $Val) {
3820 $SymbolInfo{$Version}{$InfoId}{"Value"} = $Val;
3821 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003822 }
3823 set_Class_And_Namespace($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003824 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3825 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003826 if(not defined $TypeInfo{$Version}{$ClassId}
3827 or not $TypeInfo{$Version}{$ClassId}{"Name"})
3828 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003829 delete($SymbolInfo{$Version}{$InfoId});
3830 return;
3831 }
3832 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003833 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
3834 { # extern "C"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003835 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003836 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003837 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003838 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003839 { # --lang=C option
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003840 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003841 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04003842 if(not $CheckHeadersOnly)
3843 {
3844 if(not $SymbolInfo{$Version}{$InfoId}{"Class"})
3845 {
3846 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
3847 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
3848 {
3849 if(link_symbol($ShortName, $Version, "-Deps"))
3850 { # "const" global data is mangled as _ZL... in the TU dump
3851 # but not mangled when compiling a C shared library
3852 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3853 }
3854 }
3855 }
3856 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003857 if($COMMON_LANGUAGE{$Version} eq "C++")
3858 {
3859 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3860 { # for some symbols (_ZTI) the short name is the mangled name
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003861 if(index($ShortName, "_Z")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003862 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3863 }
3864 }
3865 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3866 { # try to mangle symbol (link with libraries)
3867 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = linkSymbol($InfoId);
3868 }
3869 if($OStarget eq "windows")
3870 {
3871 if(my $Mangled = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
3872 { # link MS C++ symbols from library with GCC symbols from headers
3873 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
3874 }
3875 }
3876 }
3877 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) {
3878 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3879 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003880 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3881 {
3882 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
3883 { # non-target symbols
3884 delete($SymbolInfo{$Version}{$InfoId});
3885 return;
3886 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003887 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003888 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
3889 {
3890 if(defined $MissedTypedef{$Version}{$Rid})
3891 {
3892 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
3893 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
3894 }
3895 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003896 }
3897 setFuncAccess($InfoId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003898 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_ZTV")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003899 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
3900 }
3901 if($ShortName=~/\A(_Z|\?)/) {
3902 delete($SymbolInfo{$Version}{$InfoId}{"ShortName"});
3903 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003904
3905 if($ExtraDump) {
3906 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
3907 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003908}
3909
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003910sub isConstType($$)
3911{
3912 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003913 my %Base = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003914 while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003915 %Base = get_OneStep_BaseType($Base{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003916 }
3917 return ($Base{"Type"} eq "Const");
3918}
3919
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003920sub getTrivialName($$)
3921{
3922 my ($TypeInfoId, $TypeId) = @_;
3923 my %TypeAttr = ();
3924 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId);
3925 if(not $TypeAttr{"Name"}) {
3926 $TypeAttr{"Name"} = getTreeTypeName($TypeId);
3927 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003928 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003929 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003930 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003931 if(isAnon($TypeAttr{"Name"}))
3932 {
3933 my $NameSpaceId = $TypeId;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003934 while(my $NSId = getTreeAttr_Scpe(getTypeDeclId($NameSpaceId)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003935 { # searching for a first not anon scope
3936 if($NSId eq $NameSpaceId) {
3937 last;
3938 }
3939 else
3940 {
3941 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId));
3942 if(not $TypeAttr{"NameSpace"}
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003943 or not isAnon($TypeAttr{"NameSpace"})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003944 last;
3945 }
3946 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003947 $NameSpaceId = $NSId;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003948 }
3949 }
3950 else
3951 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003952 if(my $NameSpaceId = getTreeAttr_Scpe($TypeInfoId))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003953 {
3954 if($NameSpaceId ne $TypeId) {
3955 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId);
3956 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003957 }
3958 }
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003959 if($TypeAttr{"NameSpace"} and not isAnon($TypeAttr{"Name"})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003960 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3961 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003962 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003963 if(isAnon($TypeAttr{"Name"}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003964 { # anon-struct-header.h-line
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003965 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003966 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003967 if($TypeAttr{"NameSpace"}) {
3968 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3969 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003970 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003971 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId}
3972 and getTypeDeclId($TypeId) eq $TypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003973 {
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04003974 if(my @TParams = getTParams($TypeId, "Type")) {
3975 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T");
3976 }
3977 else {
3978 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."<...>", "T");
3979 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003980 }
3981 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"});
3982}
3983
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003984sub getTrivialTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003985{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003986 my $TypeId = $_[0];
3987 my $TypeInfoId = getTypeDeclId($_[0]);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003988
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003989 my %TypeAttr = ();
3990
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003991 if($TemplateDecl{$Version}{$TypeId})
3992 { # template_decl
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003993 $TypeAttr{"Template"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003994 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003995
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003996 setTypeAccess($TypeId, \%TypeAttr);
3997 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
3998 if(isBuiltIn($TypeAttr{"Header"}))
3999 {
4000 delete($TypeAttr{"Header"});
4001 delete($TypeAttr{"Line"});
4002 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04004003
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004004 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004005 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId);
4006 if(not $TypeAttr{"Name"}) {
4007 return ();
4008 }
4009 if(not $TypeAttr{"NameSpace"}) {
4010 delete($TypeAttr{"NameSpace"});
4011 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004012
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04004013 if($TypeAttr{"Type"} eq "Intrinsic")
4014 {
4015 if(defined $TypeAttr{"Header"})
4016 {
4017 if($TypeAttr{"Header"}=~/\Adump[1-2]\.[ih]\Z/)
4018 { # support for SUSE 11.2
4019 # integer_type has srcp dump{1-2}.i
4020 delete($TypeAttr{"Header"});
4021 }
4022 }
4023 }
4024
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004025 my $Tmpl = undef;
4026
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004027 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004028 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004029 $Tmpl = $BasicTemplate{$Version}{$TypeId};
4030
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004031 if(my @TParams = getTParams($TypeId, "Type"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004032 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004033 foreach my $Pos (0 .. $#TParams)
4034 {
4035 my $Val = $TParams[$Pos];
4036 $TypeAttr{"TParam"}{$Pos}{"name"} = $Val;
4037
4038 if(not defined $TypeAttr{"Template"})
4039 {
4040 my %Base = get_BaseType($TemplateInstance{$Version}{"Type"}{$TypeId}{$Pos}, $Version);
4041
4042 if($Base{"Type"} eq "TemplateParam"
4043 or defined $Base{"Template"}) {
4044 $TypeAttr{"Template"} = 1;
4045 }
4046 }
4047
4048 if($Tmpl)
4049 {
4050 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
4051 {
4052 $TemplateMap{$Version}{$TypeId}{$Arg} = $Val;
4053
4054 if($Val eq $Arg) {
4055 $TypeAttr{"Template"} = 1;
4056 }
4057 }
4058 }
4059 }
4060
4061 if($Tmpl)
4062 {
4063 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
4064 {
4065 if($Pos>$#TParams)
4066 {
4067 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
4068 $TemplateMap{$Version}{$TypeId}{$Arg} = "";
4069 }
4070 }
4071 }
4072 }
4073
4074 if($ADD_TMPL_INSTANCES)
4075 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004076 if($Tmpl)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004077 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004078 if(my $MainInst = getTreeAttr_Type($Tmpl))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004079 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004080 if(not getTreeAttr_Flds($TypeId))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004081 {
4082 if(my $Flds = getTreeAttr_Flds($MainInst)) {
4083 $LibInfo{$Version}{"info"}{$TypeId} .= " flds: \@$Flds ";
4084 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004085 }
4086 if(not getTreeAttr_Binf($TypeId))
4087 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004088 if(my $Binf = getTreeAttr_Binf($MainInst)) {
4089 $LibInfo{$Version}{"info"}{$TypeId} .= " binf: \@$Binf ";
4090 }
4091 }
4092 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004093 }
4094 }
4095 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004096
4097 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr);
4098
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004099 if(my $Size = getSize($TypeId))
4100 {
4101 $Size = $Size/$BYTE_SIZE;
4102 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004103 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004104 else
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004105 {
4106 if($ExtraDump)
4107 {
4108 if(not defined $TypeAttr{"Memb"}
4109 and not $Tmpl)
4110 { # declaration only
4111 $TypeAttr{"Forward"} = 1;
4112 }
4113 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004114 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004115
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004116 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004117 and ($StaticFields or detect_lang($TypeId)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004118 {
4119 $TypeAttr{"Type"} = "Class";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004120 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004121 }
4122 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004123 or $TypeAttr{"Type"} eq "Class")
4124 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004125 my $Skip = setBaseClasses($TypeId, \%TypeAttr);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004126 if($Skip) {
4127 return ();
4128 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004129 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004130 if(my $Algn = getAlgn($TypeId)) {
4131 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
4132 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004133 setSpec($TypeId, \%TypeAttr);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004134
4135 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/)
4136 {
4137 if(not $TypedefToAnon{$TypeId}
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004138 and not defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004139 {
4140 if(not isAnon($TypeAttr{"Name"})) {
4141 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"};
4142 }
4143 }
4144 }
4145
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004146 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004147 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}})
4148 {
4149 my @Entries = split(/\n/, $VTable);
4150 foreach (1 .. $#Entries)
4151 {
4152 my $Entry = $Entries[$_];
4153 if($Entry=~/\A(\d+)\s+(.+)\Z/) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004154 $TypeAttr{"VTable"}{$1} = simplifyVTable($2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004155 }
4156 }
4157 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004158
4159 if($TypeAttr{"Type"} eq "Enum")
4160 {
4161 if(not $TypeAttr{"NameSpace"})
4162 {
4163 foreach my $Pos (keys(%{$TypeAttr{"Memb"}}))
4164 {
4165 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004166 my $MVal = $TypeAttr{"Memb"}{$Pos}{"value"};
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004167 $EnumConstants{$Version}{$MName} = {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004168 "Value"=>$MVal,
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004169 "Header"=>$TypeAttr{"Header"}
4170 };
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004171 if(isAnon($TypeAttr{"Name"}))
4172 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004173 if($ExtraDump
4174 or is_target_header($TypeAttr{"Header"}, $Version))
4175 {
4176 %{$Constants{$Version}{$MName}} = (
4177 "Value" => $MVal,
4178 "Header" => $TypeAttr{"Header"}
4179 );
4180 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004181 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004182 }
4183 }
4184 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004185 if($ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004186 {
4187 if(defined $TypedefToAnon{$TypeId}) {
4188 $TypeAttr{"AnonTypedef"} = 1;
4189 }
4190 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004191
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004192 return %TypeAttr;
4193}
4194
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004195sub simplifyVTable($)
4196{
4197 my $Content = $_[0];
4198 if($Content=~s/ \[with (.+)]//)
4199 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
4200 if(my @Elems = separate_Params($1, 0, 0))
4201 {
4202 foreach my $Elem (@Elems)
4203 {
4204 if($Elem=~/\A(.+?)\s*=\s*(.+?)\Z/)
4205 {
4206 my ($Arg, $Val) = ($1, $2);
4207
4208 if(defined $DEFAULT_STD_ARGS{$Arg}) {
4209 $Content=~s/,\s*$Arg\b//g;
4210 }
4211 else {
4212 $Content=~s/\b$Arg\b/$Val/g;
4213 }
4214 }
4215 }
4216 }
4217 }
4218
4219 return $Content;
4220}
4221
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004222sub detect_lang($)
4223{
4224 my $TypeId = $_[0];
4225 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004226 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004227 { # GCC 4 fncs-node points to only non-artificial methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004228 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /);
4229 }
4230 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004231 { # GCC 3
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004232 my $Fncs = getTreeAttr_Fncs($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004233 while($Fncs)
4234 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004235 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004236 return 1;
4237 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004238 $Fncs = getTreeAttr_Chan($Fncs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004239 }
4240 }
4241 return 0;
4242}
4243
4244sub setSpec($$)
4245{
4246 my ($TypeId, $TypeAttr) = @_;
4247 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
4248 if($Info=~/\s+spec\s+/) {
4249 $TypeAttr->{"Spec"} = 1;
4250 }
4251}
4252
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004253sub setBaseClasses($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004254{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004255 my ($TypeId, $TypeAttr) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004256 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004257 if(my $Binf = getTreeAttr_Binf($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004258 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004259 my $Info = $LibInfo{$Version}{"info"}{$Binf};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004260 my $Pos = 0;
4261 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //)
4262 {
4263 my ($Access, $BInfoId) = ($1, $2);
4264 my $ClassId = getBinfClassId($BInfoId);
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004265
4266 if($ClassId==$TypeId)
4267 { # class A<N>:public A<N-1>
4268 next;
4269 }
4270
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004271 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId};
4272 if(not $CType or $CType eq "template_type_parm"
4273 or $CType eq "typename_type")
4274 { # skip
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004275 # return 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004276 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004277 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId};
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004278 if($Access=~/prot/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004279 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected";
4280 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004281 elsif($Access=~/priv/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004282 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private";
4283 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004284 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004285 if($BaseInfo=~/virt/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004286 { # virtual base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004287 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1;
4288 }
4289 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004290 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004291 }
4292 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004293 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004294}
4295
4296sub getBinfClassId($)
4297{
4298 my $Info = $LibInfo{$Version}{"info"}{$_[0]};
4299 $Info=~/type[ ]*:[ ]*@(\d+) /;
4300 return $1;
4301}
4302
4303sub unmangledFormat($$)
4304{
4305 my ($Name, $LibVersion) = @_;
4306 $Name = uncover_typedefs($Name, $LibVersion);
4307 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){};
4308 $Name=~s/\(\w+\)(\d)/$1/;
4309 return $Name;
4310}
4311
4312sub modelUnmangled($$)
4313{
4314 my ($InfoId, $Compiler) = @_;
4315 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) {
4316 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId};
4317 }
4318 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4319 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4320 $PureSignature = "~".$PureSignature;
4321 }
4322 if(not $SymbolInfo{$Version}{$InfoId}{"Data"})
4323 {
4324 my (@Params, @ParamTypes) = ();
4325 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"}
4326 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4327 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}});
4328 }
4329 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4330 { # checking parameters
4331 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004332 my $PName = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004333 my %PType = get_PureType($PId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004334 my $PTName = unmangledFormat($PType{"Name"}, $Version);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004335
4336 if($PName eq "this"
4337 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method")
4338 {
4339 next;
4340 }
4341
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004342 $PTName=~s/\b(restrict|register)\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004343 if($Compiler eq "MSVC") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004344 $PTName=~s/\blong long\b/__int64/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004345 }
4346 @ParamTypes = (@ParamTypes, $PTName);
4347 }
4348 if(@ParamTypes) {
4349 $PureSignature .= "(".join(", ", @ParamTypes).")";
4350 }
4351 else
4352 {
4353 if($Compiler eq "MSVC")
4354 {
4355 $PureSignature .= "(void)";
4356 }
4357 else
4358 { # GCC
4359 $PureSignature .= "()";
4360 }
4361 }
4362 $PureSignature = delete_keywords($PureSignature);
4363 }
4364 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
4365 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004366 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004367 $PureSignature = $ClassName."::".$PureSignature;
4368 }
4369 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) {
4370 $PureSignature = $NS."::".$PureSignature;
4371 }
4372 if($SymbolInfo{$Version}{$InfoId}{"Const"}) {
4373 $PureSignature .= " const";
4374 }
4375 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) {
4376 $PureSignature .= " volatile";
4377 }
4378 my $ShowReturn = 0;
4379 if($Compiler eq "MSVC"
4380 and $SymbolInfo{$Version}{$InfoId}{"Data"})
4381 {
4382 $ShowReturn=1;
4383 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004384 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId}
4385 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004386 {
4387 $ShowReturn=1;
4388 }
4389 if($ShowReturn)
4390 { # mangled names for template function specializations include return value
4391 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
4392 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004393 my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004394 my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
4395 $PureSignature = $ReturnName." ".$PureSignature;
4396 }
4397 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004398 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature, "S"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004399}
4400
4401sub mangle_symbol($$$)
4402{ # mangling for simple methods
4403 # see gcc-4.6.0/gcc/cp/mangle.c
4404 my ($InfoId, $LibVersion, $Compiler) = @_;
4405 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) {
4406 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler};
4407 }
4408 my $Mangled = "";
4409 if($Compiler eq "GCC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004410 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004411 }
4412 elsif($Compiler eq "MSVC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004413 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004414 }
4415 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled);
4416}
4417
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004418sub mangle_symbol_MSVC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004419{
4420 my ($InfoId, $LibVersion) = @_;
4421 return "";
4422}
4423
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004424sub mangle_symbol_GCC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004425{ # see gcc-4.6.0/gcc/cp/mangle.c
4426 my ($InfoId, $LibVersion) = @_;
4427 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004428 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004429 my %Repl = ();# SN_ replacements
4430 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
4431 {
4432 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl);
4433 if($MangledClass!~/\AN/) {
4434 $MangledClass = "N".$MangledClass;
4435 }
4436 else {
4437 $MangledClass=~s/E\Z//;
4438 }
4439 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) {
4440 $MangledClass=~s/\AN/NV/;
4441 }
4442 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) {
4443 $MangledClass=~s/\AN/NK/;
4444 }
4445 $Mangled .= $MangledClass;
4446 }
4447 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"})
4448 { # mangled by name due to the absence of structured info
4449 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl);
4450 if($MangledNS!~/\AN/) {
4451 $MangledNS = "N".$MangledNS;
4452 }
4453 else {
4454 $MangledNS=~s/E\Z//;
4455 }
4456 $Mangled .= $MangledNS;
4457 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004458 my ($ShortName, $TmplParams) = template_Base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004459 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004460 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004461 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004462 foreach (@TPos) {
4463 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"});
4464 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004465 }
4466 elsif($TmplParams)
4467 { # remangling mode
4468 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004469 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004470 }
4471 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) {
4472 $Mangled .= "C1";
4473 }
4474 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4475 $Mangled .= "D0";
4476 }
4477 elsif($ShortName)
4478 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004479 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4480 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004481 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004482 and isConstType($Return, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004483 { # "const" global data is mangled as _ZL...
4484 $Mangled .= "L";
4485 }
4486 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004487 if($ShortName=~/\Aoperator(\W.*)\Z/)
4488 {
4489 my $Op = $1;
4490 $Op=~s/\A[ ]+//g;
4491 if(my $OpMngl = $OperatorMangling{$Op}) {
4492 $Mangled .= $OpMngl;
4493 }
4494 else { # conversion operator
4495 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl);
4496 }
4497 }
4498 else {
4499 $Mangled .= length($ShortName).$ShortName;
4500 }
4501 if(@TParams)
4502 { # templates
4503 $Mangled .= "I";
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04004504 foreach my $TParam (@TParams) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004505 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl);
4506 }
4507 $Mangled .= "E";
4508 }
4509 if(not $ClassId and @TParams) {
4510 add_substitution($ShortName, \%Repl, 0);
4511 }
4512 }
4513 if($ClassId or $NameSpace) {
4514 $Mangled .= "E";
4515 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004516 if(@TParams)
4517 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004518 if($Return) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004519 $Mangled .= mangle_param($Return, $LibVersion, \%Repl);
4520 }
4521 }
4522 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4523 {
4524 my @Params = ();
4525 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
4526 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4527 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
4528 }
4529 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4530 { # checking parameters
4531 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"};
4532 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl);
4533 }
4534 if(not @Params) {
4535 $Mangled .= "v";
4536 }
4537 }
4538 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled);
4539 $Mangled = write_stdcxx_substitution($Mangled);
4540 if($Mangled eq "_Z") {
4541 return "";
4542 }
4543 return $Mangled;
4544}
4545
4546sub correct_incharge($$$)
4547{
4548 my ($InfoId, $LibVersion, $Mangled) = @_;
4549 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"})
4550 {
4551 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004552 $Mangled=~s/C1([EI])/C2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004553 }
4554 }
4555 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
4556 {
4557 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004558 $Mangled=~s/D0([EI])/D1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004559 }
4560 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004561 $Mangled=~s/D1([EI])/D2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004562 }
4563 }
4564 return $Mangled;
4565}
4566
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004567sub template_Base($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004568{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004569 # NOTE: operators: >>, <<
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004570 my $Name = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004571 if($Name!~/>\Z/ or $Name!~/</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004572 return $Name;
4573 }
4574 my $TParams = $Name;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004575 while(my $CPos = find_center($TParams, "<"))
4576 { # search for the last <T>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004577 $TParams = substr($TParams, $CPos);
4578 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004579 if($TParams=~s/\A<(.+)>\Z/$1/) {
4580 $Name=~s/<\Q$TParams\E>\Z//;
4581 }
4582 else
4583 { # error
4584 $TParams = "";
4585 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004586 return ($Name, $TParams);
4587}
4588
4589sub get_sub_ns($)
4590{
4591 my $Name = $_[0];
4592 my @NS = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004593 while(my $CPos = find_center($Name, ":"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004594 {
4595 push(@NS, substr($Name, 0, $CPos));
4596 $Name = substr($Name, $CPos);
4597 $Name=~s/\A:://;
4598 }
4599 return (join("::", @NS), $Name);
4600}
4601
4602sub mangle_ns($$$)
4603{
4604 my ($Name, $LibVersion, $Repl) = @_;
4605 if(my $Tid = $TName_Tid{$LibVersion}{$Name})
4606 {
4607 my $Mangled = mangle_param($Tid, $LibVersion, $Repl);
4608 $Mangled=~s/\AN(.+)E\Z/$1/;
4609 return $Mangled;
4610
4611 }
4612 else
4613 {
4614 my ($MangledNS, $SubNS) = ("", "");
4615 ($SubNS, $Name) = get_sub_ns($Name);
4616 if($SubNS) {
4617 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4618 }
4619 $MangledNS .= length($Name).$Name;
4620 add_substitution($MangledNS, $Repl, 0);
4621 return $MangledNS;
4622 }
4623}
4624
4625sub mangle_param($$$)
4626{
4627 my ($PTid, $LibVersion, $Repl) = @_;
4628 my ($MPrefix, $Mangled) = ("", "");
4629 my %ReplCopy = %{$Repl};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004630 my %BaseType = get_BaseType($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004631 my $BaseType_Name = $BaseType{"Name"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004632 $BaseType_Name=~s/\A(struct|union|enum) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004633 if(not $BaseType_Name) {
4634 return "";
4635 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004636 my ($ShortName, $TmplParams) = template_Base($BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004637 my $Suffix = get_BaseTypeQual($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004638 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){};
4639 while($Suffix=~/(&|\*|const)\Z/)
4640 {
4641 if($Suffix=~s/[ ]*&\Z//) {
4642 $MPrefix .= "R";
4643 }
4644 if($Suffix=~s/[ ]*\*\Z//) {
4645 $MPrefix .= "P";
4646 }
4647 if($Suffix=~s/[ ]*const\Z//)
4648 {
4649 if($MPrefix=~/R|P/
4650 or $Suffix=~/&|\*/) {
4651 $MPrefix .= "K";
4652 }
4653 }
4654 if($Suffix=~s/[ ]*volatile\Z//) {
4655 $MPrefix .= "V";
4656 }
4657 #if($Suffix=~s/[ ]*restrict\Z//) {
4658 #$MPrefix .= "r";
4659 #}
4660 }
4661 if(my $Token = $IntrinsicMangling{$BaseType_Name}) {
4662 $Mangled .= $Token;
4663 }
4664 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/)
4665 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004666 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004667 if(my @TPos = keys(%{$BaseType{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004668 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004669 foreach (@TPos) {
4670 push(@TParams, $BaseType{"TParam"}{$_}{"name"});
4671 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004672 }
4673 elsif($TmplParams)
4674 { # remangling mode
4675 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004676 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004677 }
4678 my $MangledNS = "";
4679 my ($SubNS, $SName) = get_sub_ns($ShortName);
4680 if($SubNS) {
4681 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4682 }
4683 $MangledNS .= length($SName).$SName;
4684 if(@TParams) {
4685 add_substitution($MangledNS, $Repl, 0);
4686 }
4687 $Mangled .= "N".$MangledNS;
4688 if(@TParams)
4689 { # templates
4690 $Mangled .= "I";
4691 foreach my $TParam (@TParams) {
4692 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl);
4693 }
4694 $Mangled .= "E";
4695 }
4696 $Mangled .= "E";
4697 }
4698 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/)
4699 {
4700 if($BaseType{"Type"} eq "MethodPtr") {
4701 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F";
4702 }
4703 else {
4704 $Mangled .= "PF";
4705 }
4706 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4707 my @Params = keys(%{$BaseType{"Param"}});
4708 foreach my $Num (sort {int($a)<=>int($b)} @Params) {
4709 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl);
4710 }
4711 if(not @Params) {
4712 $Mangled .= "v";
4713 }
4714 $Mangled .= "E";
4715 }
4716 elsif($BaseType{"Type"} eq "FieldPtr")
4717 {
4718 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl);
4719 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4720 }
4721 $Mangled = $MPrefix.$Mangled;# add prefix (RPK)
4722 if(my $Optimized = write_substitution($Mangled, \%ReplCopy))
4723 {
4724 if($Mangled eq $Optimized)
4725 {
4726 if($ShortName!~/::/)
4727 { # remove "N ... E"
4728 if($MPrefix) {
4729 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g;
4730 }
4731 else {
4732 $Mangled=~s/\AN(.+)E\Z/$1/g;
4733 }
4734 }
4735 }
4736 else {
4737 $Mangled = $Optimized;
4738 }
4739 }
4740 add_substitution($Mangled, $Repl, 1);
4741 return $Mangled;
4742}
4743
4744sub mangle_template_param($$$)
4745{ # types + literals
4746 my ($TParam, $LibVersion, $Repl) = @_;
4747 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) {
4748 return mangle_param($TPTid, $LibVersion, $Repl);
4749 }
4750 elsif($TParam=~/\A(\d+)(\w+)\Z/)
4751 { # class_name<1u>::method(...)
4752 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E";
4753 }
4754 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/)
4755 { # class_name<(signed char)1>::method(...)
4756 return "L".$IntrinsicMangling{$1}.$2."E";
4757 }
4758 elsif($TParam eq "true")
4759 { # class_name<true>::method(...)
4760 return "Lb1E";
4761 }
4762 elsif($TParam eq "false")
4763 { # class_name<true>::method(...)
4764 return "Lb0E";
4765 }
4766 else { # internal error
4767 return length($TParam).$TParam;
4768 }
4769}
4770
4771sub add_substitution($$$)
4772{
4773 my ($Value, $Repl, $Rec) = @_;
4774 if($Rec)
4775 { # subtypes
4776 my @Subs = ($Value);
4777 while($Value=~s/\A(R|P|K)//) {
4778 push(@Subs, $Value);
4779 }
4780 foreach (reverse(@Subs)) {
4781 add_substitution($_, $Repl, 0);
4782 }
4783 return;
4784 }
4785 return if($Value=~/\AS(\d*)_\Z/);
4786 $Value=~s/\AN(.+)E\Z/$1/g;
4787 return if(defined $Repl->{$Value});
4788 return if(length($Value)<=1);
4789 return if($StdcxxMangling{$Value});
4790 # check for duplicates
4791 my $Base = $Value;
4792 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4793 {
4794 my $Num = $Repl->{$Type};
4795 my $Replace = macro_mangle($Num);
4796 $Base=~s/\Q$Replace\E/$Type/;
4797 }
4798 if(my $OldNum = $Repl->{$Base})
4799 {
4800 $Repl->{$Value} = $OldNum;
4801 return;
4802 }
4803 my @Repls = sort {$b<=>$a} values(%{$Repl});
4804 if(@Repls) {
4805 $Repl->{$Value} = $Repls[0]+1;
4806 }
4807 else {
4808 $Repl->{$Value} = -1;
4809 }
4810 # register duplicates
4811 # upward
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004812 $Base = $Value;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004813 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4814 {
4815 next if($Base eq $Type);
4816 my $Num = $Repl->{$Type};
4817 my $Replace = macro_mangle($Num);
4818 $Base=~s/\Q$Type\E/$Replace/;
4819 $Repl->{$Base} = $Repl->{$Value};
4820 }
4821}
4822
4823sub macro_mangle($)
4824{
4825 my $Num = $_[0];
4826 if($Num==-1) {
4827 return "S_";
4828 }
4829 else
4830 {
4831 my $Code = "";
4832 if($Num<10)
4833 { # S0_, S1_, S2_, ...
4834 $Code = $Num;
4835 }
4836 elsif($Num>=10 and $Num<=35)
4837 { # SA_, SB_, SC_, ...
4838 $Code = chr(55+$Num);
4839 }
4840 else
4841 { # S10_, S11_, S12_
4842 $Code = $Num-26; # 26 is length of english alphabet
4843 }
4844 return "S".$Code."_";
4845 }
4846}
4847
4848sub write_stdcxx_substitution($)
4849{
4850 my $Mangled = $_[0];
4851 if($StdcxxMangling{$Mangled}) {
4852 return $StdcxxMangling{$Mangled};
4853 }
4854 else
4855 {
4856 my @Repls = keys(%StdcxxMangling);
4857 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4858 foreach my $MangledType (@Repls)
4859 {
4860 my $Replace = $StdcxxMangling{$MangledType};
4861 #if($Mangled!~/$Replace/) {
4862 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4863 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4864 #}
4865 }
4866 }
4867 return $Mangled;
4868}
4869
4870sub write_substitution($$)
4871{
4872 my ($Mangled, $Repl) = @_;
4873 if(defined $Repl->{$Mangled}
4874 and my $MnglNum = $Repl->{$Mangled}) {
4875 $Mangled = macro_mangle($MnglNum);
4876 }
4877 else
4878 {
4879 my @Repls = keys(%{$Repl});
4880 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls;
4881 # FIXME: how to apply replacements? by num or by pos
4882 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4883 foreach my $MangledType (@Repls)
4884 {
4885 my $Replace = macro_mangle($Repl->{$MangledType});
4886 if($Mangled!~/$Replace/) {
4887 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4888 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4889 }
4890 }
4891 }
4892 return $Mangled;
4893}
4894
4895sub delete_keywords($)
4896{
4897 my $TypeName = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004898 $TypeName=~s/\b(enum|struct|union|class) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004899 return $TypeName;
4900}
4901
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004902sub uncover_typedefs($$)
4903{
4904 my ($TypeName, $LibVersion) = @_;
4905 return "" if(not $TypeName);
4906 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) {
4907 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName};
4908 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004909 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName, "T"), "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004910 while($TypeName_New ne $TypeName_Pre)
4911 {
4912 $TypeName_Pre = $TypeName_New;
4913 my $TypeName_Copy = $TypeName_New;
4914 my %Words = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004915 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004916 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004917 if(not $Intrinsic_Keywords{$1}) {
4918 $Words{$1} = 1;
4919 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004920 }
4921 foreach my $Word (keys(%Words))
4922 {
4923 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word};
4924 next if(not $BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004925 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004926 if($BaseType_Name=~/\([\*]+\)/)
4927 { # FuncPtr
4928 if($TypeName_New=~/\Q$Word\E(.*)\Z/)
4929 {
4930 my $Type_Suffix = $1;
4931 $TypeName_New = $BaseType_Name;
4932 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004933 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004934 }
4935 }
4936 }
4937 else
4938 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004939 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004940 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004941 }
4942 }
4943 }
4944 }
4945 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New);
4946}
4947
4948sub isInternal($)
4949{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004950 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4951 {
4952 if($Info=~/mngl[ ]*:[ ]*@(\d+) /)
4953 {
4954 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/)
4955 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL*
4956 return 1;
4957 }
4958 }
4959 }
4960 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004961}
4962
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004963sub getDataVal($$)
4964{
4965 my ($InfoId, $TypeId) = @_;
4966 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4967 {
4968 if($Info=~/init[ ]*:[ ]*@(\d+) /)
4969 {
4970 if(defined $LibInfo{$Version}{"info_type"}{$1}
4971 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004972 {
4973 if(my $Nop = getTreeAttr_Op($1))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004974 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004975 if(defined $LibInfo{$Version}{"info_type"}{$Nop}
4976 and $LibInfo{$Version}{"info_type"}{$Nop} eq "addr_expr")
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004977 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004978 if(my $Addr = getTreeAttr_Op($1)) {
4979 return getInitVal($Addr, $TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004980 }
4981 }
4982 }
4983 }
4984 else {
4985 return getInitVal($1, $TypeId);
4986 }
4987 }
4988 }
4989 return undef;
4990}
4991
4992sub getInitVal($$)
4993{
4994 my ($InfoId, $TypeId) = @_;
4995 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4996 {
4997 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId})
4998 {
4999 if($InfoType eq "integer_cst")
5000 {
5001 my $Val = getNodeIntCst($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005002 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005003 { # characters
5004 $Val = chr($Val);
5005 }
5006 return $Val;
5007 }
5008 elsif($InfoType eq "string_cst") {
5009 return getNodeStrCst($InfoId);
5010 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005011 elsif($InfoType eq "var_decl")
5012 {
5013 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) {
5014 return $Name;
5015 }
5016 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005017 }
5018 }
5019 return undef;
5020}
5021
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005022sub set_Class_And_Namespace($)
5023{
5024 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005025 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005026 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005027 if($Info=~/scpe[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005028 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005029 my $NSInfoId = $1;
5030 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
5031 {
5032 if($InfoType eq "namespace_decl") {
5033 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId);
5034 }
5035 elsif($InfoType eq "record_type") {
5036 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId;
5037 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005038 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005039 }
5040 }
5041 if($SymbolInfo{$Version}{$InfoId}{"Class"}
5042 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005043 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005044 if($COMMON_LANGUAGE{$Version} ne "C++")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005045 { # skip
5046 return 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005047 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005048 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005049
5050 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005051}
5052
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005053sub debugMangling($)
5054{
5055 my $LibVersion = $_[0];
5056 my %Mangled = ();
5057 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
5058 {
5059 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
5060 {
5061 if($Mngl=~/\A(_Z|\?)/) {
5062 $Mangled{$Mngl}=$InfoId;
5063 }
5064 }
5065 }
5066 translateSymbols(keys(%Mangled), $LibVersion);
5067 foreach my $Mngl (keys(%Mangled))
5068 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005069 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC");
5070 my $U2 = $tr_name{$Mngl};
5071 if($U1 ne $U2) {
5072 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005073 }
5074 }
5075}
5076
5077sub linkSymbol($)
5078{ # link symbols from shared libraries
5079 # with the symbols from header files
5080 my $InfoId = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005081 # try to mangle symbol
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005082 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005083 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5084 or $EMERGENCY_MODE_48)
5085 { # GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
5086 # GCC 4.x doesn't mangle C++ functions in the TU dump (only class methods) except extern "C" functions
5087 # GCC 4.8 doesn't mangle anything
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005088 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005089 {
5090 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
5091 return correct_incharge($InfoId, $Version, $Mangled);
5092 }
5093 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005094 if($CheckHeadersOnly
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005095 or not $BinaryOnly
5096 or $EMERGENCY_MODE_48)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005097 { # 1. --headers-only mode
5098 # 2. not mangled src-only symbols
5099 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) {
5100 return $Mangled;
5101 }
5102 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005103 }
5104 return "";
5105}
5106
5107sub setLanguage($$)
5108{
5109 my ($LibVersion, $Lang) = @_;
5110 if(not $UserLang) {
5111 $COMMON_LANGUAGE{$LibVersion} = $Lang;
5112 }
5113}
5114
5115sub getSymbolInfo($)
5116{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005117 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005118 if(isInternal($InfoId)) {
5119 return;
5120 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005121 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
5122 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005123 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"}))
5124 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005125 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005126 return;
5127 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005128 setFuncAccess($InfoId);
5129 setFuncKind($InfoId);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005130 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"})
5131 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005132 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005133 return;
5134 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005135
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005136 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005137 if(my $Return = getFuncReturn($InfoId))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005138 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005139 if(not defined $TypeInfo{$Version}{$Return}
5140 or not $TypeInfo{$Version}{$Return}{"Name"})
5141 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005142 delete($SymbolInfo{$Version}{$InfoId});
5143 return;
5144 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005145 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Return;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005146 }
5147 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
5148 {
5149 if(defined $MissedTypedef{$Version}{$Rid})
5150 {
5151 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
5152 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
5153 }
5154 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005155 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005156 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) {
5157 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005158 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005159 my $Orig = getFuncOrig($InfoId);
5160 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005161 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "\._")!=-1)
5162 {
5163 delete($SymbolInfo{$Version}{$InfoId});
5164 return;
5165 }
5166
5167 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "tmp_add_func")==0)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005168 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005169 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005170 return;
5171 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005172
5173 if(defined $TemplateInstance{$Version}{"Func"}{$Orig})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005174 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005175 my $Tmpl = $BasicTemplate{$Version}{$InfoId};
5176
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005177 my @TParams = getTParams($Orig, "Func");
5178 if(not @TParams)
5179 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005180 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005181 return;
5182 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005183 foreach my $Pos (0 .. $#TParams)
5184 {
5185 my $Val = $TParams[$Pos];
5186 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"} = $Val;
5187
5188 if($Tmpl)
5189 {
5190 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
5191 {
5192 $TemplateMap{$Version}{$InfoId}{$Arg} = $Val;
5193 }
5194 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005195 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005196
5197 if($Tmpl)
5198 {
5199 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
5200 {
5201 if($Pos>$#TParams)
5202 {
5203 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
5204 $TemplateMap{$Version}{$InfoId}{$Arg} = "";
5205 }
5206 }
5207 }
5208
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005209 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/)
5210 { # operator<< <T>, operator>> <T>
5211 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " ";
5212 }
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04005213 if(@TParams) {
5214 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".join(", ", @TParams).">";
5215 }
5216 else {
5217 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<...>";
5218 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005219 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "S");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005220 }
5221 else
5222 { # support for GCC 3.4
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005223 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005224 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005225 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
5226 {
5227 if($OSgroup eq "windows")
5228 { # cut the offset
5229 $MnglName=~s/\@\d+\Z//g;
5230 }
5231 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
5232
5233 # NOTE: mangling of some symbols may change depending on GCC version
5234 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
5235 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
5236 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005237
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005238 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005239 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005240 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005241 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005242 return;
5243 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005244 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005245 { # destructors have an empty parameter list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005246 my $Skip = setFuncParams($InfoId);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005247 if($Skip)
5248 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005249 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005250 return;
5251 }
5252 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005253 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) {
5254 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1;
5255 }
5256
5257 if(set_Class_And_Namespace($InfoId))
5258 {
5259 delete($SymbolInfo{$Version}{$InfoId});
5260 return;
5261 }
5262
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005263 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
5264 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005265 if(not defined $TypeInfo{$Version}{$ClassId}
5266 or not $TypeInfo{$Version}{$ClassId}{"Name"})
5267 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005268 delete($SymbolInfo{$Version}{$InfoId});
5269 return;
5270 }
5271 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005272 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
5273 { # extern "C"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005274 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005275 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005276 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005277 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005278 { # --lang=C option
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005279 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005280 }
5281 if($COMMON_LANGUAGE{$Version} eq "C++")
5282 { # correct mangled & short names
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005283 # C++ or --headers-only mode
5284 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005285 { # support for old GCC versions: reconstruct real names for constructors and destructors
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005286 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"}));
5287 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005288 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005289 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005290 { # try to mangle symbol (link with libraries)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005291 if(my $Mangled = linkSymbol($InfoId)) {
5292 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005293 }
5294 }
5295 if($OStarget eq "windows")
5296 { # link MS C++ symbols from library with GCC symbols from headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005297 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005298 { # exported symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005299 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005300 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005301 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005302 { # pure virtual symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005303 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005304 }
5305 }
5306 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005307 else
5308 { # not mangled in C
5309 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5310 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005311 if(not $CheckHeadersOnly
5312 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function"
5313 and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5314 {
5315 my $Incorrect = 0;
5316
5317 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
5318 {
5319 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")==0
5320 and not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
5321 { # mangled in the TU dump, but not mangled in the library
5322 $Incorrect = 1;
5323 }
5324 }
5325 else
5326 {
5327 if($SymbolInfo{$Version}{$InfoId}{"Lang"} ne "C")
5328 { # all C++ functions are not mangled in the TU dump
5329 $Incorrect = 1;
5330 }
5331 }
5332 if($Incorrect)
5333 {
5334 if(link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps")) {
5335 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5336 }
5337 }
5338 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005339 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005340 { # can't detect symbol name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005341 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005342 return;
5343 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005344 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005345 and my $Spec = getVirtSpec($Orig))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005346 { # identify virtual and pure virtual functions
5347 # NOTE: constructors cannot be virtual
5348 # NOTE: in GCC 4.7 D1 destructors have no virtual spec
5349 # in the TU dump, so taking it from the original symbol
5350 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"}
5351 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/))
5352 { # NOTE: D2 destructors are not present in a v-table
5353 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1;
5354 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005355 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005356 if(isInline($InfoId)) {
5357 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005358 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04005359 if(hasThrow($InfoId)) {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005360 $SymbolInfo{$Version}{$InfoId}{"Throw"} = 1;
5361 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005362 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5363 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005364 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005365 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"}
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04005366 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005367 { # inline or auto-generated constructor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005368 delete($TypeInfo{$Version}{$ClassId}{"Copied"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005369 }
5370 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005371 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
5372 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005373 if(not $ExtraDump)
5374 {
5375 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
5376 { # non-target symbols
5377 delete($SymbolInfo{$Version}{$InfoId});
5378 return;
5379 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005380 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005381 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005382 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method"
5383 or $SymbolInfo{$Version}{$InfoId}{"Constructor"}
5384 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}
5385 or $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005386 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005387 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/)
5388 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005389 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005390 return;
5391 }
5392 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005393 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005394 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005395 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005396 { # one instance for one mangled name only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005397 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005398 return;
5399 }
5400 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005401 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005402 }
5403 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005404 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5405 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
5406 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005407 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005408 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/
5409 and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005410 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005411 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005412 { # static methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005413 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005414 }
5415 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005416 if(getFuncLink($InfoId) eq "Static") {
5417 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005418 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005419 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/)
5420 {
5421 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
5422 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005423 if($Unmangled=~/\.\_\d/)
5424 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005425 delete($SymbolInfo{$Version}{$InfoId});
5426 return;
5427 }
5428 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005429 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005430
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005431 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) {
5432 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005433 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005434 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) {
5435 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005436 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005437
5438 if($WeakSymbols{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) {
5439 $SymbolInfo{$Version}{$InfoId}{"Weak"} = 1;
5440 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005441
5442 if($ExtraDump) {
5443 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
5444 }
5445}
5446
5447sub guessHeader($)
5448{
5449 my $InfoId = $_[0];
5450 my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5451 my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"};
5452 my $ClassName = $ClassId?get_ShortClass($ClassId, $Version):"";
5453 my $Header = $SymbolInfo{$Version}{$InfoId}{"Header"};
5454 if(my $HPath = $SymbolHeader{$Version}{$ClassName}{$ShortName})
5455 {
5456 if(get_filename($HPath) eq $Header)
5457 {
5458 my $HDir = get_filename(get_dirname($HPath));
5459 if($HDir ne "include"
5460 and $HDir=~/\A[a-z]+\Z/i) {
5461 return join_P($HDir, $Header);
5462 }
5463 }
5464 }
5465 return $Header;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005466}
5467
5468sub isInline($)
5469{ # "body: undefined" in the tree
5470 # -fkeep-inline-functions GCC option should be specified
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005471 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5472 {
5473 if($Info=~/ undefined /i) {
5474 return 0;
5475 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005476 }
5477 return 1;
5478}
5479
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005480sub hasThrow($)
5481{
5482 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5483 {
5484 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5485 return getTreeAttr_Unql($1, "unql");
5486 }
5487 }
5488 return 1;
5489}
5490
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005491sub getTypeId($)
5492{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005493 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5494 {
5495 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5496 return $1;
5497 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005498 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005499 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005500}
5501
5502sub setTypeMemb($$)
5503{
5504 my ($TypeId, $TypeAttr) = @_;
5505 my $TypeType = $TypeAttr->{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005506 my ($Pos, $UnnamedPos) = (0, 0);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005507 my $StaticFields = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005508 if($TypeType eq "Enum")
5509 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005510 my $MInfoId = getTreeAttr_Csts($TypeId);
5511 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005512 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005513 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId);
5514 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005515 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005516 $EnumMembName_Id{$Version}{getTreeAttr_Valu($MInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
5517 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005518 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005519 }
5520 }
5521 elsif($TypeType=~/\A(Struct|Class|Union)\Z/)
5522 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005523 my $MInfoId = getTreeAttr_Flds($TypeId);
5524 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005525 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005526 my $IType = $LibInfo{$Version}{"info_type"}{$MInfoId};
5527 my $MInfo = $LibInfo{$Version}{"info"}{$MInfoId};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005528 if(not $IType or $IType ne "field_decl")
5529 { # search for fields, skip other stuff in the declaration
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005530
5531 if($IType eq "var_decl")
5532 { # static field
5533 $StaticFields = 1;
5534 }
5535
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005536 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005537 next;
5538 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005539 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId));
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005540 if(index($StructMembName, "_vptr.")==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005541 { # virtual tables
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005542 $StructMembName = "_vptr";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005543 }
5544 if(not $StructMembName)
5545 { # unnamed fields
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005546 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005547 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005548 my $UnnamedTid = getTreeAttr_Type($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005549 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid));
5550 if(isAnon($UnnamedTName))
5551 { # rename unnamed fields to unnamed0, unnamed1, ...
5552 $StructMembName = "unnamed".($UnnamedPos++);
5553 }
5554 }
5555 }
5556 if(not $StructMembName)
5557 { # unnamed fields and base classes
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005558 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005559 next;
5560 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005561 my $MembTypeId = getTreeAttr_Type($MInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005562 if(defined $MissedTypedef{$Version}{$MembTypeId})
5563 {
5564 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) {
5565 $MembTypeId = $AddedTid;
5566 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005567 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005568
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005569 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId;
5570 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005571 if((my $Access = getTreeAccess($MInfoId)) ne "public")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005572 { # marked only protected and private, public by default
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005573 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access;
5574 }
5575 if($MInfo=~/spec:\s*mutable /)
5576 { # mutable fields
5577 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005578 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005579 if(my $Algn = getAlgn($MInfoId)) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005580 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
5581 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005582 if(my $BFSize = getBitField($MInfoId))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005583 { # in bits
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005584 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005585 }
5586 else
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005587 { # in bytes
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005588 if($TypeAttr->{"Memb"}{$Pos}{"algn"}==1)
5589 { # template
5590 delete($TypeAttr->{"Memb"}{$Pos}{"algn"});
5591 }
5592 else {
5593 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
5594 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005595 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005596
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005597 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005598 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005599 }
5600 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005601
5602 return $StaticFields;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005603}
5604
5605sub setFuncParams($)
5606{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005607 my $InfoId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005608 my $ParamInfoId = getTreeAttr_Args($InfoId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005609
5610 my $FType = getFuncType($InfoId);
5611
5612 if($FType eq "Method")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005613 { # check type of "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005614 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId);
5615 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005616 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005617 if($ObjectName=~/\bconst(| volatile)\*const\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005618 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
5619 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005620 if($ObjectName=~/\bvolatile\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005621 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
5622 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005623 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005624 else
5625 { # skip
5626 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005627 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +04005628 # skip "this"-parameter
5629 # $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005630 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005631 my ($Pos, $PPos, $Vtt_Pos) = (0, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005632 while($ParamInfoId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005633 { # formal args
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005634 my $ParamTypeId = getTreeAttr_Type($ParamInfoId);
5635 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId));
5636 if(not $ParamName)
5637 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005638 $ParamName = "p".($PPos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005639 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005640 if(defined $MissedTypedef{$Version}{$ParamTypeId})
5641 {
5642 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) {
5643 $ParamTypeId = $AddedTid;
5644 }
5645 }
5646 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005647 if(not $PType or $PType eq "Unknown") {
5648 return 1;
5649 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005650 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005651 if(not $PTName) {
5652 return 1;
5653 }
5654 if($PTName eq "void") {
5655 last;
5656 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005657 if($ParamName eq "__vtt_parm"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005658 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005659 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005660 $Vtt_Pos = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005661 $ParamInfoId = getNextElem($ParamInfoId);
5662 next;
5663 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005664 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005665
5666 if(my %Base = get_BaseType($ParamTypeId, $Version))
5667 {
5668 if(defined $Base{"Template"}) {
5669 return 1;
5670 }
5671 }
5672
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005673 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005674 if(my $Algn = getAlgn($ParamInfoId)) {
5675 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
5676 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005677 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /)
5678 { # foo(register type arg)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005679 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005680 }
5681 $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005682 $Pos += 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005683 if($ParamName ne "this" or $FType ne "Method") {
5684 $PPos += 1;
5685 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005686 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005687 if(setFuncArgs($InfoId, $Vtt_Pos)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005688 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = "-1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005689 }
5690 return 0;
5691}
5692
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005693sub setFuncArgs($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005694{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005695 my ($InfoId, $Vtt_Pos) = @_;
5696 my $FuncTypeId = getFuncTypeId($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005697 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005698 my $FType = getFuncType($InfoId);
5699
5700 if($FType eq "Method")
5701 {
5702 # skip "this"-parameter
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005703 # $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005704 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005705 if(not $ParamListElemId)
5706 { # foo(...)
5707 return 1;
5708 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005709 my $HaveVoid = 0;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005710 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005711 while($ParamListElemId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005712 { # actual params: may differ from formal args
5713 # formal int*const
5714 # actual: int*
5715 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005716 {
5717 $Vtt_Pos=-1;
5718 $ParamListElemId = getNextElem($ParamListElemId);
5719 next;
5720 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005721 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId);
5722 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005723 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005724 $HaveVoid = 1;
5725 last;
5726 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005727 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005728 {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005729 if(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5730 {
5731 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5732 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5733 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005734 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($PPos+1);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005735 }
5736 }
5737 elsif(my $OldId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5738 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04005739 if($Pos>0 or getFuncType($InfoId) ne "Method")
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005740 { # params
5741 if($OldId ne $ParamTypeId)
5742 {
5743 my %Old_Pure = get_PureType($OldId, $TypeInfo{$Version});
5744 my %New_Pure = get_PureType($ParamTypeId, $TypeInfo{$Version});
5745
5746 if($Old_Pure{"Name"} ne $New_Pure{"Name"}) {
5747 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5748 }
5749 }
5750 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005751 }
5752 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005753 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005754 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005755 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5756 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005757 if($PurpType eq "nop_expr")
5758 { # func ( const char* arg = (const char*)(void*)0 )
5759 $PurpId = getTreeAttr_Op($PurpId);
5760 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005761 my $Val = getInitVal($PurpId, $ParamTypeId);
5762 if(defined $Val) {
5763 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5764 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005765 }
5766 }
5767 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005768 if($Pos!=0 or $FType ne "Method") {
5769 $PPos += 1;
5770 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005771 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005772 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005773 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005774}
5775
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005776sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005777{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005778 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5779 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005780 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5781 return $1;
5782 }
5783 }
5784 return "";
5785}
5786
5787sub getTreeAttr_Chain($)
5788{
5789 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5790 {
5791 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5792 return $1;
5793 }
5794 }
5795 return "";
5796}
5797
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005798sub getTreeAttr_Unql($)
5799{
5800 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5801 {
5802 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5803 return $1;
5804 }
5805 }
5806 return "";
5807}
5808
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005809sub getTreeAttr_Scpe($)
5810{
5811 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5812 {
5813 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5814 return $1;
5815 }
5816 }
5817 return "";
5818}
5819
5820sub getTreeAttr_Type($)
5821{
5822 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5823 {
5824 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5825 return $1;
5826 }
5827 }
5828 return "";
5829}
5830
5831sub getTreeAttr_Name($)
5832{
5833 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5834 {
5835 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5836 return $1;
5837 }
5838 }
5839 return "";
5840}
5841
5842sub getTreeAttr_Mngl($)
5843{
5844 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5845 {
5846 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5847 return $1;
5848 }
5849 }
5850 return "";
5851}
5852
5853sub getTreeAttr_Prms($)
5854{
5855 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5856 {
5857 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5858 return $1;
5859 }
5860 }
5861 return "";
5862}
5863
5864sub getTreeAttr_Fncs($)
5865{
5866 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5867 {
5868 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5869 return $1;
5870 }
5871 }
5872 return "";
5873}
5874
5875sub getTreeAttr_Csts($)
5876{
5877 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5878 {
5879 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5880 return $1;
5881 }
5882 }
5883 return "";
5884}
5885
5886sub getTreeAttr_Purp($)
5887{
5888 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5889 {
5890 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5891 return $1;
5892 }
5893 }
5894 return "";
5895}
5896
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005897sub getTreeAttr_Op($)
5898{
5899 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5900 {
5901 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) {
5902 return $1;
5903 }
5904 }
5905 return "";
5906}
5907
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005908sub getTreeAttr_Valu($)
5909{
5910 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5911 {
5912 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5913 return $1;
5914 }
5915 }
5916 return "";
5917}
5918
5919sub getTreeAttr_Flds($)
5920{
5921 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5922 {
5923 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5924 return $1;
5925 }
5926 }
5927 return "";
5928}
5929
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005930sub getTreeAttr_Binf($)
5931{
5932 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5933 {
5934 if($Info=~/binf[ ]*:[ ]*@(\d+) /) {
5935 return $1;
5936 }
5937 }
5938 return "";
5939}
5940
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005941sub getTreeAttr_Args($)
5942{
5943 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5944 {
5945 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005946 return $1;
5947 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005948 }
5949 return "";
5950}
5951
5952sub getTreeValue($)
5953{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005954 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5955 {
5956 if($Info=~/low[ ]*:[ ]*([^ ]+) /) {
5957 return $1;
5958 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005959 }
5960 return "";
5961}
5962
5963sub getTreeAccess($)
5964{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005965 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005966 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005967 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5968 {
5969 my $Access = $1;
5970 if($Access eq "prot") {
5971 return "protected";
5972 }
5973 elsif($Access eq "priv") {
5974 return "private";
5975 }
5976 }
5977 elsif($Info=~/ protected /)
5978 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005979 return "protected";
5980 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005981 elsif($Info=~/ private /)
5982 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005983 return "private";
5984 }
5985 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005986 return "public";
5987}
5988
5989sub setFuncAccess($)
5990{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005991 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005992 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005993 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005994 }
5995 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005996 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005997 }
5998}
5999
6000sub setTypeAccess($$)
6001{
6002 my ($TypeId, $TypeAttr) = @_;
6003 my $Access = getTreeAccess($TypeId);
6004 if($Access eq "protected") {
6005 $TypeAttr->{"Protected"} = 1;
6006 }
6007 elsif($Access eq "private") {
6008 $TypeAttr->{"Private"} = 1;
6009 }
6010}
6011
6012sub setFuncKind($)
6013{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006014 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6015 {
6016 if($Info=~/pseudo tmpl/) {
6017 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
6018 }
6019 elsif($Info=~/ constructor /) {
6020 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
6021 }
6022 elsif($Info=~/ destructor /) {
6023 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
6024 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006025 }
6026}
6027
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006028sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006029{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006030 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6031 {
6032 if($Info=~/spec[ ]*:[ ]*pure /) {
6033 return "PureVirt";
6034 }
6035 elsif($Info=~/spec[ ]*:[ ]*virt /) {
6036 return "Virt";
6037 }
6038 elsif($Info=~/ pure\s+virtual /)
6039 { # support for old GCC versions
6040 return "PureVirt";
6041 }
6042 elsif($Info=~/ virtual /)
6043 { # support for old GCC versions
6044 return "Virt";
6045 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006046 }
6047 return "";
6048}
6049
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006050sub getFuncLink($)
6051{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006052 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6053 {
6054 if($Info=~/link[ ]*:[ ]*static /) {
6055 return "Static";
6056 }
6057 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006058 return $1;
6059 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006060 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006061 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006062}
6063
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006064sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006065{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006066 my ($Symbol, $LibVersion) = @_;
6067 return "" if(not $Symbol or not $LibVersion);
6068 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
6069 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006070 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006071 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
6072 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
6073 }
6074 }
6075 if($NS)
6076 {
6077 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6078 return $NS;
6079 }
6080 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006081 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006082 while($NS=~s/::[^:]+\Z//)
6083 {
6084 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6085 return $NS;
6086 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006087 }
6088 }
6089 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006090
6091 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006092}
6093
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006094sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006095{
6096 my ($TypeName, $LibVersion) = @_;
6097 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006098 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006099 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006100 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6101 return $NS;
6102 }
6103 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006104 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006105 while($NS=~s/::[^:]+\Z//)
6106 {
6107 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6108 return $NS;
6109 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006110 }
6111 }
6112 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006113 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006114}
6115
6116sub getNameSpace($)
6117{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006118 my $InfoId = $_[0];
6119 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006120 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006121 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006122 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006123 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006124 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006125 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
6126 {
6127 my $NameSpace = getTreeStr($1);
6128 if($NameSpace eq "::")
6129 { # global namespace
6130 return "";
6131 }
6132 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
6133 $NameSpace = $BaseNameSpace."::".$NameSpace;
6134 }
6135 $NestedNameSpaces{$Version}{$NameSpace} = 1;
6136 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006137 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006138 else {
6139 return "";
6140 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006141 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04006142 elsif($InfoType ne "function_decl")
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006143 { # inside data type
6144 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
6145 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006146 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006147 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006148 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006149 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006150}
6151
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006152sub getEnumMembVal($)
6153{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006154 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006155 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006156 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
6157 {
6158 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
6159 {
6160 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
6161 { # in newer versions of GCC the value is in the "const_decl->cnst" node
6162 return getTreeValue($1);
6163 }
6164 else
6165 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
6166 return getTreeValue($1);
6167 }
6168 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006169 }
6170 }
6171 return "";
6172}
6173
6174sub getSize($)
6175{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006176 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6177 {
6178 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
6179 return getTreeValue($1);
6180 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006181 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006182 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006183}
6184
6185sub getAlgn($)
6186{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006187 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6188 {
6189 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
6190 return $1;
6191 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006192 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006193 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006194}
6195
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04006196sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006197{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006198 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6199 {
6200 if($Info=~/ bitfield /) {
6201 return getSize($_[0]);
6202 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006203 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006204 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006205}
6206
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006207sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006208{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006209 if(my $Chan = getTreeAttr_Chan($_[0])) {
6210 return $Chan;
6211 }
6212 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
6213 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006214 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006215 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006216}
6217
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006218sub registerHeader($$)
6219{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006220 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006221 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006222 return "";
6223 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006224 if(is_abs($Header) and not -f $Header)
6225 { # incorrect absolute path
6226 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006227 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006228 if(skipHeader($Header, $LibVersion))
6229 { # skip
6230 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006231 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006232 if(my $Header_Path = identifyHeader($Header, $LibVersion))
6233 {
6234 detect_header_includes($Header_Path, $LibVersion);
6235
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006236 if(defined $Tolerance and $Tolerance=~/3/)
6237 { # 3 - skip headers that include non-Linux headers
6238 if($OSgroup ne "windows")
6239 {
6240 foreach my $Inc (keys(%{$Header_Includes{$LibVersion}{$Header_Path}}))
6241 {
6242 if(specificHeader($Inc, "windows")) {
6243 return "";
6244 }
6245 }
6246 }
6247 }
6248
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006249 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
6250 { # redirect
6251 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
6252 or skipHeader($RHeader_Path, $LibVersion))
6253 { # skip
6254 return "";
6255 }
6256 $Header_Path = $RHeader_Path;
6257 }
6258 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
6259 { # skip
6260 return "";
6261 }
6262
6263 if(my $HName = get_filename($Header_Path))
6264 { # register
6265 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
6266 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
6267 }
6268
6269 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
6270 or $Header!~/\.(\w+)\Z/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006271 { # hpp, hh, etc.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006272 setLanguage($LibVersion, "C++");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006273 $CPP_HEADERS = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006274 }
6275
6276 if($CheckHeadersOnly
6277 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
6278 { # /usr/include/c++/4.6.1/...
6279 $STDCXX_TESTING = 1;
6280 }
6281
6282 return $Header_Path;
6283 }
6284 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006285}
6286
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006287sub registerDir($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006288{
6289 my ($Dir, $WithDeps, $LibVersion) = @_;
6290 $Dir=~s/[\/\\]+\Z//g;
6291 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006292 $Dir = get_abs_path($Dir);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04006293
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006294 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006295 if($WithDeps)
6296 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006297 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
6298 return;
6299 }
6300 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
6301 $Mode = "DepsOnly";
6302 }
6303 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006304 else
6305 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006306 if($RegisteredDirs{$LibVersion}{$Dir}{1}
6307 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
6308 return;
6309 }
6310 }
6311 $Header_Dependency{$LibVersion}{$Dir} = 1;
6312 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
6313 if($Mode eq "DepsOnly")
6314 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006315 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006316 $Header_Dependency{$LibVersion}{$Path} = 1;
6317 }
6318 return;
6319 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006320 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006321 {
6322 if($WithDeps)
6323 {
6324 my $SubDir = $Path;
6325 while(($SubDir = get_dirname($SubDir)) ne $Dir)
6326 { # register all sub directories
6327 $Header_Dependency{$LibVersion}{$SubDir} = 1;
6328 }
6329 }
6330 next if(is_not_header($Path));
6331 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006332 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006333 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006334 $Include_Neighbors{$LibVersion}{$Part} = $Path;
6335 }
6336 }
6337 if(get_filename($Dir) eq "include")
6338 { # search for "lib/include/" directory
6339 my $LibDir = $Dir;
6340 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006341 registerDir($LibDir, $WithDeps, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006342 }
6343 }
6344}
6345
6346sub parse_redirect($$$)
6347{
6348 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006349 my @Errors = ();
6350 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
6351 push(@Errors, $1);
6352 }
6353 my $Redirect = "";
6354 foreach (@Errors)
6355 {
6356 s/\s{2,}/ /g;
6357 if(/(only|must\ include
6358 |update\ to\ include
6359 |replaced\ with
6360 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006361 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006362 {
6363 $Redirect = $2;
6364 last;
6365 }
6366 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
6367 {
6368 $Redirect = $2;
6369 last;
6370 }
6371 elsif(/this\ header\ should\ not\ be\ used
6372 |programs\ should\ not\ directly\ include
6373 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
6374 |is\ not\ supported\ API\ for\ general\ use
6375 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006376 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006377 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
6378 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6379 }
6380 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006381 if($Redirect)
6382 {
6383 $Redirect=~s/\A<//g;
6384 $Redirect=~s/>\Z//g;
6385 }
6386 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006387}
6388
6389sub parse_includes($$)
6390{
6391 my ($Content, $Path) = @_;
6392 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006393 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006394 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04006395 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006396 my $Method = substr($Header, 0, 1, "");
6397 substr($Header, length($Header)-1, 1, "");
6398 $Header = path_format($Header, $OSgroup);
6399 if($Method eq "\"" or is_abs($Header))
6400 {
6401 if(-e join_P(get_dirname($Path), $Header))
6402 { # relative path exists
6403 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006404 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006405 else
6406 { # include "..." that doesn't exist is equal to include <...>
6407 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006408 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006409 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006410 else {
6411 $Includes{$Header} = 1;
6412 }
6413 }
6414 if($ExtraInfo)
6415 {
6416 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
6417 { # FT_FREETYPE_H
6418 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006419 }
6420 }
6421 return \%Includes;
6422}
6423
6424sub ignore_path($)
6425{
6426 my $Path = $_[0];
6427 if($Path=~/\~\Z/)
6428 {# skipping system backup files
6429 return 1;
6430 }
6431 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
6432 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
6433 return 1;
6434 }
6435 return 0;
6436}
6437
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006438sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006439{
6440 my ($ArrRef, $W) = @_;
6441 return if(length($W)<2);
6442 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
6443}
6444
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006445sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006446{
6447 my ($H1, $H2) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006448
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006449 $H1=~s/\.[a-z]+\Z//ig;
6450 $H2=~s/\.[a-z]+\Z//ig;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006451
6452 my $Hname1 = get_filename($H1);
6453 my $Hname2 = get_filename($H2);
6454 my $HDir1 = get_dirname($H1);
6455 my $HDir2 = get_dirname($H2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006456 my $Dirname1 = get_filename($HDir1);
6457 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006458
6459 $HDir1=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6460 $HDir2=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6461
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006462 if($_[0] eq $_[1]
6463 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006464 return 0;
6465 }
6466 elsif($H1=~/\A\Q$H2\E/) {
6467 return 1;
6468 }
6469 elsif($H2=~/\A\Q$H1\E/) {
6470 return -1;
6471 }
6472 elsif($HDir1=~/\Q$Hname1\E/i
6473 and $HDir2!~/\Q$Hname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006474 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006475 return -1;
6476 }
6477 elsif($HDir2=~/\Q$Hname2\E/i
6478 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006479 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006480 return 1;
6481 }
6482 elsif($Hname1=~/\Q$Dirname1\E/i
6483 and $Hname2!~/\Q$Dirname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006484 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006485 return -1;
6486 }
6487 elsif($Hname2=~/\Q$Dirname2\E/i
6488 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006489 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006490 return 1;
6491 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006492 elsif($Hname1=~/(config|lib|util)/i
6493 and $Hname2!~/(config|lib|util)/i)
6494 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006495 return -1;
6496 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006497 elsif($Hname2=~/(config|lib|util)/i
6498 and $Hname1!~/(config|lib|util)/i)
6499 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006500 return 1;
6501 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006502 else
6503 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006504 my $R1 = checkRelevance($H1);
6505 my $R2 = checkRelevance($H2);
6506 if($R1 and not $R2)
6507 { # libebook/e-book.h
6508 return -1;
6509 }
6510 elsif($R2 and not $R1)
6511 { # libebook/e-book.h
6512 return 1;
6513 }
6514 else
6515 {
6516 return (lc($H1) cmp lc($H2));
6517 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006518 }
6519}
6520
6521sub searchForHeaders($)
6522{
6523 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006524
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006525 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006526 registerGccHeaders();
6527
6528 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
6529 { # c++ standard include paths
6530 registerCppHeaders();
6531 }
6532
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006533 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006534 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
6535 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006536 {
6537 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006538 if($SystemRoot)
6539 {
6540 if(is_abs($Path)) {
6541 $Path = $SystemRoot.$Path;
6542 }
6543 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006544 if(not -e $Path) {
6545 exitStatus("Access_Error", "can't access \'$Path\'");
6546 }
6547 elsif(-f $Path) {
6548 exitStatus("Access_Error", "\'$Path\' - not a directory");
6549 }
6550 elsif(-d $Path)
6551 {
6552 $Path = get_abs_path($Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006553 registerDir($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006554 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
6555 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006556 }
6557 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006558 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006559 }
6560 }
6561 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006562 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006563 $INC_PATH_AUTODETECT{$LibVersion} = 0;
6564 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006565
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006566 # registering directories
6567 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6568 {
6569 next if(not -e $Path);
6570 $Path = get_abs_path($Path);
6571 $Path = path_format($Path, $OSgroup);
6572 if(-d $Path) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006573 registerDir($Path, 1, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006574 }
6575 elsif(-f $Path)
6576 {
6577 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006578 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006579 and not $LocalIncludes{$Dir})
6580 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006581 registerDir($Dir, 1, $LibVersion);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006582 # if(my $OutDir = get_dirname($Dir))
6583 # { # registering the outer directory
6584 # if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
6585 # and not $LocalIncludes{$OutDir}) {
6586 # registerDir($OutDir, 0, $LibVersion);
6587 # }
6588 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006589 }
6590 }
6591 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006592
6593 # clean memory
6594 %RegisteredDirs = ();
6595
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006596 # registering headers
6597 my $Position = 0;
6598 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6599 {
6600 if(is_abs($Dest) and not -e $Dest) {
6601 exitStatus("Access_Error", "can't access \'$Dest\'");
6602 }
6603 $Dest = path_format($Dest, $OSgroup);
6604 if(is_header($Dest, 1, $LibVersion))
6605 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006606 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006607 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
6608 }
6609 }
6610 elsif(-d $Dest)
6611 {
6612 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006613 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006614 {
6615 next if(ignore_path($Path));
6616 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006617 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006618 push(@Registered, $HPath);
6619 }
6620 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006621 @Registered = sort {sortHeaders($a, $b)} @Registered;
6622 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006623 foreach my $Path (@Registered) {
6624 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
6625 }
6626 }
6627 else {
6628 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
6629 }
6630 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006631
6632 if(defined $Tolerance and $Tolerance=~/4/)
6633 { # 4 - skip headers included by others
6634 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
6635 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006636 if(defined $Header_Includes_R{$LibVersion}{$Path}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006637 delete($Registered_Headers{$LibVersion}{$Path});
6638 }
6639 }
6640 }
6641
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006642 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
6643 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006644 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006645 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006646 if(is_abs($Header) and not -f $Header) {
6647 exitStatus("Access_Error", "can't access file \'$Header\'");
6648 }
6649 $Header = path_format($Header, $OSgroup);
6650 if(my $Header_Path = is_header($Header, 1, $LibVersion))
6651 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006652 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006653 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006654 }
6655 else {
6656 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
6657 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006658 }
6659 }
6660 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
6661 { # set relative paths (for duplicates)
6662 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
6663 { # search for duplicates
6664 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
6665 my $Prefix = get_dirname($FirstPath);
6666 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6667 { # detect a shortest distinguishing prefix
6668 my $NewPrefix = $1;
6669 my %Identity = ();
6670 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6671 {
6672 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6673 $Identity{$Path} = $1;
6674 }
6675 }
6676 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6677 { # all names are differend with current prefix
6678 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6679 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6680 }
6681 last;
6682 }
6683 $Prefix = $NewPrefix; # increase prefix
6684 }
6685 }
6686 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006687
6688 # clean memory
6689 %HeaderName_Paths = ();
6690
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006691 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6692 { # ordering headers according to descriptor
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006693 my $PairName = $Include_Order{$LibVersion}{$HeaderName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006694 my ($Pos, $PairPos) = (-1, -1);
6695 my ($Path, $PairPath) = ();
6696 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6697 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6698 foreach my $Header_Path (@Paths)
6699 {
6700 if(get_filename($Header_Path) eq $PairName)
6701 {
6702 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6703 $PairPath = $Header_Path;
6704 }
6705 if(get_filename($Header_Path) eq $HeaderName)
6706 {
6707 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6708 $Path = $Header_Path;
6709 }
6710 }
6711 if($PairPos!=-1 and $Pos!=-1
6712 and int($PairPos)<int($Pos))
6713 {
6714 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6715 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6716 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6717 }
6718 }
6719 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6720 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6721 }
6722}
6723
6724sub detect_real_includes($$)
6725{
6726 my ($AbsPath, $LibVersion) = @_;
6727 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6728 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6729 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6730 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6731 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006732 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6733
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006734 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6735 return () if(not $Path);
6736 open(PREPROC, $Path);
6737 while(<PREPROC>)
6738 {
6739 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6740 {
6741 my $Include = path_format($1, $OSgroup);
6742 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6743 next;
6744 }
6745 if($Include eq $AbsPath) {
6746 next;
6747 }
6748 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6749 }
6750 }
6751 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006752 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6753}
6754
6755sub detect_header_includes($$)
6756{
6757 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006758 return if(not $LibVersion or not $Path);
6759 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6760 return;
6761 }
6762 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6763
6764 if(not -e $Path) {
6765 return;
6766 }
6767
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006768 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006769 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6770 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006771 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006772 {
6773 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006774 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006775 }
6776 if($RedirectPath ne $Path) {
6777 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6778 }
6779 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006780 else
6781 { # can't find
6782 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6783 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006784 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006785 if(my $Inc = parse_includes($Content, $Path))
6786 {
6787 foreach my $Include (keys(%{$Inc}))
6788 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006789 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006790
6791 if(defined $Tolerance and $Tolerance=~/4/)
6792 {
6793 if(my $HPath = identifyHeader($Include, $LibVersion))
6794 {
6795 $Header_Includes_R{$LibVersion}{$HPath}{$Path} = 1;
6796 }
6797 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006798 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006799 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006800}
6801
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006802sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006803{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006804 my $Path = $_[0];
6805 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006806 if($OStarget eq "symbian")
6807 {
6808 if(get_filename($Dir) eq "libc" and $GlibcHeader{$Name})
6809 { # epoc32/include/libc/{stdio, ...}.h
6810 return 1;
6811 }
6812 }
6813 else
6814 {
6815 if($Dir eq "/usr/include" and $GlibcHeader{$Name})
6816 { # /usr/include/{stdio, ...}.h
6817 return 1;
6818 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006819 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006820 return 0;
6821}
6822
6823sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006824{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006825 my $Dir = $_[0];
6826 my ($OutDir, $Name) = separate_path($Dir);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006827 if($OStarget eq "symbian")
6828 {
6829 if(get_filename($OutDir) eq "libc"
6830 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6831 { # epoc32/include/libc/{sys,bits,asm,asm-*}/*.h
6832 return 1;
6833 }
6834 }
6835 else
6836 { # linux
6837 if($OutDir eq "/usr/include"
6838 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6839 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6840 return 1;
6841 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006842 }
6843 return 0;
6844}
6845
6846sub detect_recursive_includes($$)
6847{
6848 my ($AbsPath, $LibVersion) = @_;
6849 return () if(not $AbsPath);
6850 if(isCyclical(\@RecurInclude, $AbsPath)) {
6851 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6852 }
6853 my ($AbsDir, $Name) = separate_path($AbsPath);
6854 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006855 { # system GLIBC internals
6856 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006857 }
6858 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6859 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6860 }
6861 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006862
6863 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6864 { # skip /usr/include/c++/*/ headers
6865 return () if(not $ExtraInfo);
6866 }
6867
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006868 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006869 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006870 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006871 { # check "real" (non-"model") include paths
6872 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6873 pop(@RecurInclude);
6874 return @Paths;
6875 }
6876 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6877 detect_header_includes($AbsPath, $LibVersion);
6878 }
6879 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6880 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006881 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006882 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006883 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006884 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006885 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006886 if(-f $Candidate) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006887 $HPath = realpath($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006888 }
6889 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006890 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006891 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006892 { # search for the nearest header
6893 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006894 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006895 if(-f $Candidate) {
6896 $HPath = $Candidate;
6897 }
6898 }
6899 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006900 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006901 }
6902 next if(not $HPath);
6903 if($HPath eq $AbsPath) {
6904 next;
6905 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006906
6907 if($Debug)
6908 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006909# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6910# {
6911# print STDERR "$AbsPath -> $HPath\n";
6912# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006913 }
6914
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006915 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6916 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006917 { # only include <...>, skip include "..." prefixes
6918 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6919 }
6920 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6921 {
6922 if($IncPath eq $AbsPath) {
6923 next;
6924 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006925 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6926 if($RIncType==-1)
6927 { # include "..."
6928 $RIncType = $IncType;
6929 }
6930 elsif($RIncType==2)
6931 {
6932 if($IncType!=-1) {
6933 $RIncType = $IncType;
6934 }
6935 }
6936 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006937 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6938 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6939 }
6940 }
6941 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6942 {
6943 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6944 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6945 { # distinguish math.h from glibc and math.h from the tested library
6946 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6947 last;
6948 }
6949 }
6950 }
6951 pop(@RecurInclude);
6952 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6953}
6954
6955sub find_in_framework($$$)
6956{
6957 my ($Header, $Framework, $LibVersion) = @_;
6958 return "" if(not $Header or not $Framework or not $LibVersion);
6959 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6960 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6961 }
6962 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6963 {
6964 if(get_filename($Dependency) eq $Framework
6965 and -f get_dirname($Dependency)."/".$Header) {
6966 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6967 }
6968 }
6969 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6970}
6971
6972sub find_in_defaults($)
6973{
6974 my $Header = $_[0];
6975 return "" if(not $Header);
6976 if(defined $Cache{"find_in_defaults"}{$Header}) {
6977 return $Cache{"find_in_defaults"}{$Header};
6978 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006979 foreach my $Dir (@DefaultIncPaths,
6980 @DefaultGccPaths,
6981 @DefaultCppPaths,
6982 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006983 {
6984 next if(not $Dir);
6985 if(-f $Dir."/".$Header) {
6986 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
6987 }
6988 }
6989 return ($Cache{"find_in_defaults"}{$Header}="");
6990}
6991
6992sub cmp_paths($$)
6993{
6994 my ($Path1, $Path2) = @_;
6995 my @Parts1 = split(/[\/\\]/, $Path1);
6996 my @Parts2 = split(/[\/\\]/, $Path2);
6997 foreach my $Num (0 .. $#Parts1)
6998 {
6999 my $Part1 = $Parts1[$Num];
7000 my $Part2 = $Parts2[$Num];
7001 if($GlibcDir{$Part1}
7002 and not $GlibcDir{$Part2}) {
7003 return 1;
7004 }
7005 elsif($GlibcDir{$Part2}
7006 and not $GlibcDir{$Part1}) {
7007 return -1;
7008 }
7009 elsif($Part1=~/glib/
7010 and $Part2!~/glib/) {
7011 return 1;
7012 }
7013 elsif($Part1!~/glib/
7014 and $Part2=~/glib/) {
7015 return -1;
7016 }
7017 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
7018 return $CmpRes;
7019 }
7020 }
7021 return 0;
7022}
7023
7024sub checkRelevance($)
7025{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007026 my $Path = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007027 return 0 if(not $Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007028
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007029 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007030 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007031 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007032
7033 my $Name = lc(get_filename($Path));
7034 my $Dir = lc(get_dirname($Path));
7035
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007036 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007037
7038 foreach my $Token (split(/[_\d\W]+/, $Name))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007039 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007040 my $Len = length($Token);
7041 next if($Len<=1);
7042 if($Dir=~/(\A|lib|[_\d\W])\Q$Token\E([_\d\W]|lib|\Z)/)
7043 { # include/evolution-data-server-1.4/libebook/e-book.h
7044 return 1;
7045 }
7046 if($Len>=4 and index($Dir, $Token)!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007047 { # include/gupnp-1.0/libgupnp/gupnp-context.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007048 return 1;
7049 }
7050 }
7051 return 0;
7052}
7053
7054sub checkFamily(@)
7055{
7056 my @Paths = @_;
7057 return 1 if($#Paths<=0);
7058 my %Prefix = ();
7059 foreach my $Path (@Paths)
7060 {
7061 if($SystemRoot) {
7062 $Path = cut_path_prefix($Path, $SystemRoot);
7063 }
7064 if(my $Dir = get_dirname($Path))
7065 {
7066 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
7067 $Prefix{$Dir} += 1;
7068 $Prefix{get_dirname($Dir)} += 1;
7069 }
7070 }
7071 foreach (sort keys(%Prefix))
7072 {
7073 if(get_depth($_)>=3
7074 and $Prefix{$_}==$#Paths+1) {
7075 return 1;
7076 }
7077 }
7078 return 0;
7079}
7080
7081sub isAcceptable($$$)
7082{
7083 my ($Header, $Candidate, $LibVersion) = @_;
7084 my $HName = get_filename($Header);
7085 if(get_dirname($Header))
7086 { # with prefix
7087 return 1;
7088 }
7089 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
7090 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
7091 return 1;
7092 }
7093 if(checkRelevance($Candidate))
7094 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
7095 return 1;
7096 }
7097 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
7098 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
7099 # /usr/include/qt4/Qt/qsslconfiguration.h
7100 return 1;
7101 }
7102 if($OStarget eq "symbian")
7103 {
7104 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
7105 return 1;
7106 }
7107 }
7108 return 0;
7109}
7110
7111sub isRelevant($$$)
7112{ # disallow to search for "abstract" headers in too deep directories
7113 my ($Header, $Candidate, $LibVersion) = @_;
7114 my $HName = get_filename($Header);
7115 if($OStarget eq "symbian")
7116 {
7117 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
7118 return 0;
7119 }
7120 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007121 if($OStarget ne "bsd")
7122 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007123 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
7124 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
7125 return 0;
7126 }
7127 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007128 if($OStarget ne "windows")
7129 {
7130 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
7131 { # skip /usr/include/wine/msvcrt
7132 return 0;
7133 }
7134 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007135 if(not get_dirname($Header)
7136 and $Candidate=~/[\/\\]wx[\/\\]/)
7137 { # do NOT search in system /wx/ directory
7138 # for headers without a prefix: sstream.h
7139 return 0;
7140 }
7141 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
7142 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
7143 { # skip ../c++/3.3.3/ if using ../c++/4.5/
7144 return 0;
7145 }
7146 if($Candidate=~/[\/\\]asm-/
7147 and (my $Arch = getArch($LibVersion)) ne "unknown")
7148 { # arch-specific header files
7149 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
7150 {# skip ../asm-arm/ if using x86 architecture
7151 return 0;
7152 }
7153 }
7154 my @Candidates = getSystemHeaders($HName, $LibVersion);
7155 if($#Candidates==1)
7156 { # unique header
7157 return 1;
7158 }
7159 my @SCandidates = getSystemHeaders($Header, $LibVersion);
7160 if($#SCandidates==1)
7161 { # unique name
7162 return 1;
7163 }
7164 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
7165 if(get_depth($Candidate)-$SystemDepth>=5)
7166 { # abstract headers in too deep directories
7167 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
7168 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
7169 return 0;
7170 }
7171 }
7172 if($Header eq "parser.h"
7173 and $Candidate!~/\/libxml2\//)
7174 { # select parser.h from xml2 library
7175 return 0;
7176 }
7177 if(not get_dirname($Header)
7178 and keys(%{$SystemHeaders{$HName}})>=3)
7179 { # many headers with the same name
7180 # like thread.h included without a prefix
7181 if(not checkFamily(@Candidates)) {
7182 return 0;
7183 }
7184 }
7185 return 1;
7186}
7187
7188sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007189{ # cache function
7190 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
7191 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
7192 }
7193 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
7194}
7195
7196sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007197{
7198 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007199 if(-f $Header) {
7200 return $Header;
7201 }
7202 if(is_abs($Header) and not -f $Header)
7203 { # incorrect absolute path
7204 return "";
7205 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007206 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007207 { # too abstract configuration headers
7208 return "";
7209 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007210 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007211 if($OSgroup ne "windows")
7212 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007213 if(defined $WinHeaders{lc($HName)}
7214 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007215 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007216 return "";
7217 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007218 }
7219 if($OSgroup ne "macos")
7220 {
7221 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007222 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007223 return "";
7224 }
7225 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007226
7227 if(defined $ObsoleteHeaders{$HName})
7228 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007229 return "";
7230 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007231 if($OSgroup eq "linux" or $OSgroup eq "bsd")
7232 {
7233 if(defined $AlienHeaders{$HName}
7234 or defined $AlienHeaders{$Header})
7235 { # alien headers from other systems
7236 return "";
7237 }
7238 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007239
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007240 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007241 { # search in default paths
7242 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007243 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007244 }
7245 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007246 if(not defined $Cache{"checkSystemFiles"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007247 { # register all headers in system include dirs
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007248 checkSystemFiles();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007249 }
7250 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
7251 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
7252 {
7253 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007254 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007255 }
7256 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007257 # error
7258 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007259}
7260
7261sub getSystemHeaders($$)
7262{
7263 my ($Header, $LibVersion) = @_;
7264 my @Candidates = ();
7265 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
7266 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007267 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007268 next;
7269 }
7270 push(@Candidates, $Candidate);
7271 }
7272 return @Candidates;
7273}
7274
7275sub cut_path_prefix($$)
7276{
7277 my ($Path, $Prefix) = @_;
7278 return $Path if(not $Prefix);
7279 $Prefix=~s/[\/\\]+\Z//;
7280 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
7281 return $Path;
7282}
7283
7284sub is_default_include_dir($)
7285{
7286 my $Dir = $_[0];
7287 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007288 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007289}
7290
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007291sub identifyHeader($$)
7292{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007293 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007294 if(not $Header) {
7295 return "";
7296 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007297 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007298 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
7299 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007300 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007301 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007302}
7303
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007304sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007305{ # search for header by absolute path, relative path or name
7306 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007307 if(-f $Header)
7308 { # it's relative or absolute path
7309 return get_abs_path($Header);
7310 }
7311 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
7312 and my $HeaderDir = find_in_defaults($Header))
7313 { # search for libc headers in the /usr/include
7314 # for non-libc target library before searching
7315 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007316 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007317 }
7318 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
7319 { # search in the target library paths
7320 return $Path;
7321 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007322 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007323 { # search in the internal GCC include paths
7324 return $DefaultGccHeader{$Header};
7325 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007326 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007327 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007328 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007329 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007330 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007331 { # search in the default G++ include paths
7332 return $DefaultCppHeader{$Header};
7333 }
7334 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
7335 { # search everywhere in the system
7336 return $AnyPath;
7337 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007338 elsif($OSgroup eq "macos")
7339 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
7340 if(my $Dir = get_dirname($Header))
7341 {
7342 my $RelPath = "Headers\/".get_filename($Header);
7343 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007344 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007345 }
7346 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007347 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007348 # cannot find anything
7349 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007350}
7351
7352sub getLocation($)
7353{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007354 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7355 {
7356 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007357 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007358 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007359 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007360 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007361}
7362
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007363sub getNameByInfo($)
7364{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007365 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007366 {
7367 if($Info=~/name[ ]*:[ ]*@(\d+) /)
7368 {
7369 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
7370 {
7371 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
7372 { # short unsigned int (may include spaces)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007373 my $Str = $1;
7374 if($CppMode{$Version}
7375 and $Str=~/\Ac99_(.+)\Z/)
7376 {
7377 if($CppKeywords_A{$1}) {
7378 $Str=$1;
7379 }
7380 }
7381 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007382 }
7383 }
7384 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007385 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007386 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007387}
7388
7389sub getTreeStr($)
7390{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007391 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007392 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007393 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
7394 {
7395 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007396 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007397 and $Str=~/\Ac99_(.+)\Z/)
7398 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007399 if($CppKeywords_A{$1}) {
7400 $Str=$1;
7401 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007402 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007403 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007404 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007405 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007406 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007407}
7408
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007409sub getFuncShortName($)
7410{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007411 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007412 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007413 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007414 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007415 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007416 {
7417 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
7418 {
7419 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
7420 return "operator ".$RName;
7421 }
7422 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007423 }
7424 else
7425 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007426 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
7427 {
7428 if(my $Ind = $Operator_Indication{$1}) {
7429 return "operator".$Ind;
7430 }
7431 elsif(not $UnknownOperator{$1})
7432 {
7433 printMsg("WARNING", "unknown operator $1");
7434 $UnknownOperator{$1} = 1;
7435 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007436 }
7437 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007438 }
7439 else
7440 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007441 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
7442 return getTreeStr($1);
7443 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007444 }
7445 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007446 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007447}
7448
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007449sub getFuncReturn($)
7450{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007451 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7452 {
7453 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7454 {
7455 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
7456 return $1;
7457 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007458 }
7459 }
7460 return "";
7461}
7462
7463sub getFuncOrig($)
7464{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007465 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7466 {
7467 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
7468 return $1;
7469 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007470 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007471 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007472}
7473
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007474sub unmangleArray(@)
7475{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007476 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007477 { # MSVC mangling
7478 my $UndNameCmd = get_CmdPath("undname");
7479 if(not $UndNameCmd) {
7480 exitStatus("Not_Found", "can't find \"undname\"");
7481 }
7482 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007483 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007484 }
7485 else
7486 { # GCC mangling
7487 my $CppFiltCmd = get_CmdPath("c++filt");
7488 if(not $CppFiltCmd) {
7489 exitStatus("Not_Found", "can't find c++filt in PATH");
7490 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007491 if(not defined $CPPFILT_SUPPORT_FILE)
7492 {
7493 my $Info = `$CppFiltCmd -h 2>&1`;
7494 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
7495 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007496 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007497 if($CPPFILT_SUPPORT_FILE)
7498 { # new versions of c++filt can take a file
7499 if($#_>$MAX_CPPFILT_FILE_SIZE)
7500 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
7501 # this is fixed in the oncoming version of Binutils
7502 my @Half = splice(@_, 0, ($#_+1)/2);
7503 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007504 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007505 else
7506 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007507 writeFile("$TMP_DIR/unmangle", join("\n", @_));
7508 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
7509 if($?==139)
7510 { # segmentation fault
7511 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
7512 }
7513 return split(/\n/, $Res);
7514 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007515 }
7516 else
7517 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007518 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
7519 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007520 my @Half = splice(@_, 0, ($#_+1)/2);
7521 return (unmangleArray(@Half), unmangleArray(@_))
7522 }
7523 else
7524 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007525 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007526 my $Res = `$CppFiltCmd $NoStrip $Strings`;
7527 if($?==139)
7528 { # segmentation fault
7529 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
7530 }
7531 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007532 }
7533 }
7534 }
7535}
7536
7537sub get_SignatureNoInfo($$)
7538{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007539 my ($Symbol, $LibVersion) = @_;
7540 if($Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol}) {
7541 return $Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007542 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007543 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007544 my $Signature = $tr_name{$MnglName}?$tr_name{$MnglName}:$MnglName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007545 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007546 { # C++
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04007547 # some standard typedefs
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007548 $Signature=~s/\Qstd::basic_string<char, std::char_traits<char>, std::allocator<char> >\E/std::string/g;
7549 $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;
7550 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007551 if(not $CheckObjectsOnly or $OSgroup=~/linux|bsd|beos/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007552 { # ELF format marks data as OBJECT
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007553 if($GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007554 $Signature .= " [data]";
7555 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007556 elsif($Symbol!~/\A(_Z|\?)/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007557 $Signature .= " (...)";
7558 }
7559 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007560 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007561 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04007562 my $ShortName = substr($Signature, 0, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007563 $Signature=~s/\A\Q$ShortName\E/$ShortName $ChargeLevel/g;
7564 }
7565 if($SymbolVersion) {
7566 $Signature .= $VersionSpec.$SymbolVersion;
7567 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007568 return ($Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007569}
7570
7571sub get_ChargeLevel($$)
7572{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007573 my ($Symbol, $LibVersion) = @_;
7574 return "" if($Symbol!~/\A(_Z|\?)/);
7575 if(defined $CompleteSignature{$LibVersion}{$Symbol}
7576 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007577 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007578 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007579 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007580 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007581 return "[in-charge]";
7582 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007583 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007584 return "[not-in-charge]";
7585 }
7586 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007587 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007588 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007589 if($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007590 return "[in-charge]";
7591 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007592 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007593 return "[not-in-charge]";
7594 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007595 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007596 return "[in-charge-deleting]";
7597 }
7598 }
7599 }
7600 else
7601 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007602 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007603 return "[in-charge]";
7604 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007605 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007606 return "[not-in-charge]";
7607 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007608 elsif($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007609 return "[in-charge]";
7610 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007611 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007612 return "[not-in-charge]";
7613 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007614 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007615 return "[in-charge-deleting]";
7616 }
7617 }
7618 return "";
7619}
7620
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007621sub get_Signature_M($$)
7622{
7623 my ($Symbol, $LibVersion) = @_;
7624 my $Signature_M = $tr_name{$Symbol};
7625 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
7626 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007627 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007628 }
7629 return $Signature_M;
7630}
7631
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007632sub get_Signature($$)
7633{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007634 my ($Symbol, $LibVersion) = @_;
7635 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
7636 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007637 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007638 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
7639 if(isPrivateData($MnglName) or not $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007640 { # non-public global data
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007641 return get_SignatureNoInfo($Symbol, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007642 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007643 my ($Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007644 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
7645 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007646 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007647 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
7648 {
7649 $Signature .= $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::";
7650 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7651 $Signature .= "~";
7652 }
7653 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007654 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007655 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007656 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007657 }
7658 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007659 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007660 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007661 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7662 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007663 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007664 else
7665 {
7666 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007667 }
7668 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007669 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007670 {
7671 next if($Pos eq "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007672 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007673 next if(not $ParamTypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007674 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007675 if(not $ParamTypeName) {
7676 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7677 }
7678 foreach my $Typedef (keys(%ChangedTypedef))
7679 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007680 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7681 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7682 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007683 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007684 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"})
7685 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007686 if($ParamName eq "this"
7687 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007688 { # do NOT show first hidded "this"-parameter
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007689 next;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007690 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007691 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007692 }
7693 else {
7694 push(@ParamArray, $ParamTypeName);
7695 }
7696 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007697 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7698 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007699 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007700 }
7701 else
7702 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007703 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007704 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007705 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007706 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007707 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007708 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7709 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007710 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007711 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007712 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7713 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007714 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007715 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007716 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7717 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007718 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007719 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007720 }
7721 }
7722 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007723 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007724 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007725 }
7726 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007727 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007728 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007729 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007730}
7731
7732sub create_member_decl($$)
7733{
7734 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007735 if($TName=~/\([\*]+\)/)
7736 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007737 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7738 return $TName;
7739 }
7740 else
7741 {
7742 my @ArraySizes = ();
7743 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7744 push(@ArraySizes, $1);
7745 }
7746 return $TName." ".$Member.join("", @ArraySizes);
7747 }
7748}
7749
7750sub getFuncType($)
7751{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007752 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7753 {
7754 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7755 {
7756 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7757 {
7758 if($Type eq "method_type") {
7759 return "Method";
7760 }
7761 elsif($Type eq "function_type") {
7762 return "Function";
7763 }
7764 else {
7765 return "Other";
7766 }
7767 }
7768 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007769 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007770 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007771}
7772
7773sub getFuncTypeId($)
7774{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007775 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7776 {
7777 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7778 return $1;
7779 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007780 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007781 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007782}
7783
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007784sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007785{ # "._N" or "$_N" in older GCC versions
7786 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007787}
7788
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007789sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007790{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007791 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7792 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007793 }
7794
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007795 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007796
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007797 if($_[1] ne "S")
7798 {
7799 $N=~s/\A[ ]+//g;
7800 $N=~s/[ ]+\Z//g;
7801 $N=~s/[ ]{2,}/ /g;
7802 }
7803
7804 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007805
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007806 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007807
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007808 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7809 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007810
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007811 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007812
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007813 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007814
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007815 if($_[1] eq "S")
7816 {
7817 if(index($N, "operator")!=-1) {
7818 $N=~s/\b(operator[ ]*)> >/$1>>/;
7819 }
7820 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007821
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007822 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007823}
7824
7825sub get_HeaderDeps($$)
7826{
7827 my ($AbsPath, $LibVersion) = @_;
7828 return () if(not $AbsPath or not $LibVersion);
7829 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7830 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7831 }
7832 my %IncDir = ();
7833 detect_recursive_includes($AbsPath, $LibVersion);
7834 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7835 {
7836 next if(not $HeaderPath);
7837 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7838 my $Dir = get_dirname($HeaderPath);
7839 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7840 {
7841 my $Dep = $Dir;
7842 if($Prefix)
7843 {
7844 if($OSgroup eq "windows")
7845 { # case insensitive seach on windows
7846 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7847 next;
7848 }
7849 }
7850 elsif($OSgroup eq "macos")
7851 { # seach in frameworks
7852 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7853 {
7854 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7855 {# frameworks
7856 my ($HFramework, $HName) = ($1, $2);
7857 $Dep = $HFramework;
7858 }
7859 else
7860 {# mismatch
7861 next;
7862 }
7863 }
7864 }
7865 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7866 { # Linux, FreeBSD
7867 next;
7868 }
7869 }
7870 if(not $Dep)
7871 { # nothing to include
7872 next;
7873 }
7874 if(is_default_include_dir($Dep))
7875 { # included by the compiler
7876 next;
7877 }
7878 if(get_depth($Dep)==1)
7879 { # too short
7880 next;
7881 }
7882 if(isLibcDir($Dep))
7883 { # do NOT include /usr/include/{sys,bits}
7884 next;
7885 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007886 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007887 }
7888 }
7889 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7890 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7891}
7892
7893sub sortIncPaths($$)
7894{
7895 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007896 if(not $ArrRef or $#{$ArrRef}<0) {
7897 return $ArrRef;
7898 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007899 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7900 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007901 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007902 return $ArrRef;
7903}
7904
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007905sub sortDeps($$$)
7906{
7907 if($Header_Dependency{$_[2]}{$_[0]}
7908 and not $Header_Dependency{$_[2]}{$_[1]}) {
7909 return 1;
7910 }
7911 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7912 and $Header_Dependency{$_[2]}{$_[1]}) {
7913 return -1;
7914 }
7915 return 0;
7916}
7917
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007918sub join_P($$)
7919{
7920 my $S = "/";
7921 if($OSgroup eq "windows") {
7922 $S = "\\";
7923 }
7924 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007925}
7926
7927sub get_namespace_additions($)
7928{
7929 my $NameSpaces = $_[0];
7930 my ($Additions, $AddNameSpaceId) = ("", 1);
7931 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7932 {
7933 next if($SkipNameSpaces{$Version}{$NS});
7934 next if(not $NS or $NameSpaces->{$NS}==-1);
7935 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7936 next if($NS=~/\A__/i);
7937 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007938 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007939 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7940 my @NS_Parts = split(/::/, $NS);
7941 next if($#NS_Parts==-1);
7942 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7943 foreach my $NS_Part (@NS_Parts)
7944 {
7945 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7946 $TypeDecl_Suffix .= "}";
7947 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007948 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007949 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7950 $Additions.=" $TypeDecl\n $FuncDecl\n";
7951 $AddNameSpaceId+=1;
7952 }
7953 return $Additions;
7954}
7955
7956sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007957{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007958 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007959 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007960 if($Fmt eq "windows")
7961 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007962 $Path=~s/\//\\/g;
7963 $Path=lc($Path);
7964 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007965 else
7966 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007967 $Path=~s/\\/\//g;
7968 }
7969 return $Path;
7970}
7971
7972sub inc_opt($$)
7973{
7974 my ($Path, $Style) = @_;
7975 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007976 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007977 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007978 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007979 return "-I\"".path_format($Path, "unix")."\"";
7980 }
7981 elsif($OSgroup eq "macos"
7982 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007983 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007984 return "-F".esc(get_dirname($Path));
7985 }
7986 else {
7987 return "-I".esc($Path);
7988 }
7989 }
7990 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007991 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007992 }
7993 return "";
7994}
7995
7996sub platformSpecs($)
7997{
7998 my $LibVersion = $_[0];
7999 my $Arch = getArch($LibVersion);
8000 if($OStarget eq "symbian")
8001 { # options for GCCE compiler
8002 my %Symbian_Opts = map {$_=>1} (
8003 "-D__GCCE__",
8004 "-DUNICODE",
8005 "-fexceptions",
8006 "-D__SYMBIAN32__",
8007 "-D__MARM_INTERWORK__",
8008 "-D_UNICODE",
8009 "-D__S60_50__",
8010 "-D__S60_3X__",
8011 "-D__SERIES60_3X__",
8012 "-D__EPOC32__",
8013 "-D__MARM__",
8014 "-D__EABI__",
8015 "-D__MARM_ARMV5__",
8016 "-D__SUPPORT_CPP_EXCEPTIONS__",
8017 "-march=armv5t",
8018 "-mapcs",
8019 "-mthumb-interwork",
8020 "-DEKA2",
8021 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
8022 );
8023 return join(" ", keys(%Symbian_Opts));
8024 }
8025 elsif($OSgroup eq "windows"
8026 and get_dumpmachine($GCC_PATH)=~/mingw/i)
8027 { # add options to MinGW compiler
8028 # to simulate the MSVC compiler
8029 my %MinGW_Opts = map {$_=>1} (
8030 "-D_WIN32",
8031 "-D_STDCALL_SUPPORTED",
8032 "-D__int64=\"long long\"",
8033 "-D__int32=int",
8034 "-D__int16=short",
8035 "-D__int8=char",
8036 "-D__possibly_notnullterminated=\" \"",
8037 "-D__nullterminated=\" \"",
8038 "-D__nullnullterminated=\" \"",
8039 "-D__w64=\" \"",
8040 "-D__ptr32=\" \"",
8041 "-D__ptr64=\" \"",
8042 "-D__forceinline=inline",
8043 "-D__inline=inline",
8044 "-D__uuidof(x)=IID()",
8045 "-D__try=",
8046 "-D__except(x)=",
8047 "-D__declspec(x)=__attribute__((x))",
8048 "-D__pragma(x)=",
8049 "-D_inline=inline",
8050 "-D__forceinline=__inline",
8051 "-D__stdcall=__attribute__((__stdcall__))",
8052 "-D__cdecl=__attribute__((__cdecl__))",
8053 "-D__fastcall=__attribute__((__fastcall__))",
8054 "-D__thiscall=__attribute__((__thiscall__))",
8055 "-D_stdcall=__attribute__((__stdcall__))",
8056 "-D_cdecl=__attribute__((__cdecl__))",
8057 "-D_fastcall=__attribute__((__fastcall__))",
8058 "-D_thiscall=__attribute__((__thiscall__))",
8059 "-DSHSTDAPI_(x)=x",
8060 "-D_MSC_EXTENSIONS",
8061 "-DSECURITY_WIN32",
8062 "-D_MSC_VER=1500",
8063 "-D_USE_DECLSPECS_FOR_SAL",
8064 "-D__noop=\" \"",
8065 "-DDECLSPEC_DEPRECATED=\" \"",
8066 "-D__builtin_alignof(x)=__alignof__(x)",
8067 "-DSORTPP_PASS");
8068 if($Arch eq "x86") {
8069 $MinGW_Opts{"-D_M_IX86=300"}=1;
8070 }
8071 elsif($Arch eq "x86_64") {
8072 $MinGW_Opts{"-D_M_AMD64=300"}=1;
8073 }
8074 elsif($Arch eq "ia64") {
8075 $MinGW_Opts{"-D_M_IA64=300"}=1;
8076 }
8077 return join(" ", keys(%MinGW_Opts));
8078 }
8079 return "";
8080}
8081
8082my %C_Structure = map {$_=>1} (
8083# FIXME: Can't separate union and struct data types before dumping,
8084# so it sometimes cause compilation errors for unknown reason
8085# when trying to declare TYPE* tmp_add_class_N
8086# This is a list of such structures + list of other C structures
8087 "sigval",
8088 "sigevent",
8089 "sigaction",
8090 "sigvec",
8091 "sigstack",
8092 "timeval",
8093 "timezone",
8094 "rusage",
8095 "rlimit",
8096 "wait",
8097 "flock",
8098 "stat",
8099 "_stat",
8100 "stat32",
8101 "_stat32",
8102 "stat64",
8103 "_stat64",
8104 "_stati64",
8105 "if_nameindex",
8106 "usb_device",
8107 "sigaltstack",
8108 "sysinfo",
8109 "timeLocale",
8110 "tcp_debug",
8111 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008112 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008113 "timespec",
8114 "random_data",
8115 "drand48_data",
8116 "_IO_marker",
8117 "_IO_FILE",
8118 "lconv",
8119 "sched_param",
8120 "tm",
8121 "itimerspec",
8122 "_pthread_cleanup_buffer",
8123 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008124 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008125 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008126 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008127 "sigcontext",
8128 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008129 # Mac
8130 "_timex",
8131 "_class_t",
8132 "_category_t",
8133 "_class_ro_t",
8134 "_protocol_t",
8135 "_message_ref_t",
8136 "_super_message_ref_t",
8137 "_ivar_t",
8138 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008139);
8140
8141sub getCompileCmd($$$)
8142{
8143 my ($Path, $Opt, $Inc) = @_;
8144 my $GccCall = $GCC_PATH;
8145 if($Opt) {
8146 $GccCall .= " ".$Opt;
8147 }
8148 $GccCall .= " -x ";
8149 if($OSgroup eq "macos") {
8150 $GccCall .= "objective-";
8151 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04008152
8153 if($EMERGENCY_MODE_48)
8154 { # workaround for GCC 4.8 (C only)
8155 $GccCall .= "c++";
8156 }
8157 elsif(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008158 { # compile as "C++" header
8159 # to obtain complete dump using GCC 4.0
8160 $GccCall .= "c++-header";
8161 }
8162 else
8163 { # compile as "C++" source
8164 # GCC 3.3 cannot compile headers
8165 $GccCall .= "c++";
8166 }
8167 if(my $Opts = platformSpecs($Version))
8168 {# platform-specific options
8169 $GccCall .= " ".$Opts;
8170 }
8171 # allow extra qualifications
8172 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008173 $GccCall .= " -fpermissive";
8174 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008175 if($NoStdInc)
8176 {
8177 $GccCall .= " -nostdinc";
8178 $GccCall .= " -nostdinc++";
8179 }
8180 if($CompilerOptions{$Version})
8181 { # user-defined options
8182 $GccCall .= " ".$CompilerOptions{$Version};
8183 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008184 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008185 if($Inc)
8186 { # include paths
8187 $GccCall .= " ".$Inc;
8188 }
8189 return $GccCall;
8190}
8191
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008192sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008193{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008194 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008195 my %HeaderElems = (
8196 # Types
8197 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008198 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008199 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
8200 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008201 "time.h" => ["time_t"],
8202 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008203 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
8204 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008205 "stdbool.h" => ["_Bool"],
8206 "rpc/xdr.h" => ["bool_t"],
8207 "in_systm.h" => ["n_long", "n_short"],
8208 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04008209 "arpa/inet.h" => ["fw_src", "ip_src"],
8210 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008211 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008212 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008213 );
8214 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008215 foreach (keys(%HeaderElems))
8216 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008217 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008218 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008219 }
8220 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008221 my %Types = ();
8222 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
8223 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008224 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008225 }
8226 if(keys(%Types))
8227 {
8228 my %AddHeaders = ();
8229 foreach my $Type (keys(%Types))
8230 {
8231 if(my $Header = $AutoPreamble{$Type})
8232 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008233 if(my $Path = identifyHeader($Header, $LibVersion))
8234 {
8235 if(skipHeader($Path, $LibVersion)) {
8236 next;
8237 }
8238 $Path = path_format($Path, $OSgroup);
8239 $AddHeaders{$Path}{"Type"} = $Type;
8240 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008241 }
8242 }
8243 }
8244 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008245 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008246 }
8247 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008248 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008249}
8250
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008251sub checkCTags($)
8252{
8253 my $Path = $_[0];
8254 if(not $Path) {
8255 return;
8256 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008257 my $CTags = undef;
8258
8259 if($OSgroup eq "bsd")
8260 { # use ectags on BSD
8261 $CTags = get_CmdPath("ectags");
8262 if(not $CTags) {
8263 printMsg("WARNING", "can't find \'ectags\' program");
8264 }
8265 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008266 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008267 $CTags = get_CmdPath("ctags");
8268 }
8269 if(not $CTags)
8270 {
8271 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008272 return;
8273 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008274
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008275 if($OSgroup ne "linux")
8276 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008277 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
8278 if($Info!~/exuberant/i)
8279 {
8280 printMsg("WARNING", "incompatible version of \'ctags\' program");
8281 return;
8282 }
8283 }
8284
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008285 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008286 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008287 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008288 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008289 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008290 open(CTAGS, "<", $Out);
8291 while(my $Line = <CTAGS>)
8292 {
8293 chomp($Line);
8294 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008295 if(defined $Intrinsic_Keywords{$Name})
8296 { # noise
8297 next;
8298 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008299 if($Type eq "n")
8300 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008301 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008302 next;
8303 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008304 if(index($Scpe, "struct:")==0) {
8305 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008306 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008307 if(index($Scpe, "namespace:")==0)
8308 {
8309 if($Scpe=~s/\Anamespace://) {
8310 $Name = $Scpe."::".$Name;
8311 }
8312 }
8313 $TUnit_NameSpaces{$Version}{$Name} = 1;
8314 }
8315 elsif($Type eq "p")
8316 {
8317 if(not $Scpe or index($Scpe, "namespace:")==0) {
8318 $TUnit_Funcs{$Version}{$Name} = 1;
8319 }
8320 }
8321 elsif($Type eq "x")
8322 {
8323 if(not $Scpe or index($Scpe, "namespace:")==0) {
8324 $TUnit_Vars{$Version}{$Name} = 1;
8325 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008326 }
8327 }
8328 close(CTAGS);
8329}
8330
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008331sub preChange($$)
8332{
8333 my ($HeaderPath, $IncStr) = @_;
8334
8335 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
8336 my $Content = undef;
8337
8338 if($OStarget eq "windows"
8339 and get_dumpmachine($GCC_PATH)=~/mingw/i
8340 and $MinGWMode{$Version}!=-1)
8341 { # modify headers to compile by MinGW
8342 if(not $Content)
8343 { # preprocessing
8344 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8345 }
8346 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
8347 { # __asm { ... }
8348 $MinGWMode{$Version}=1;
8349 }
8350 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
8351 { # comments after preprocessing
8352 $MinGWMode{$Version}=1;
8353 }
8354 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
8355 { # 0xffui8
8356 $MinGWMode{$Version}=1;
8357 }
8358
8359 if($MinGWMode{$Version}) {
8360 printMsg("INFO", "Using MinGW compatibility mode");
8361 }
8362 }
8363
8364 if(($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
8365 and $CppMode{$Version}!=-1 and not $CppCompat and not $CPP_HEADERS)
8366 { # rename C++ keywords in C code
8367 # disable this code by -cpp-compatible option
8368 if(not $Content)
8369 { # preprocessing
8370 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8371 }
8372 my $RegExp_C = join("|", keys(%CppKeywords_C));
8373 my $RegExp_F = join("|", keys(%CppKeywords_F));
8374 my $RegExp_O = join("|", keys(%CppKeywords_O));
8375
8376 my $Detected = undef;
8377
8378 while($Content=~s/(\A|\n[^\#\/\n][^\n]*?|\n)(\*\s*|\s+|\@|\,|\()($RegExp_C|$RegExp_F)(\s*(\,|\)|\;|\-\>|\.|\:\s*\d))/$1$2c99_$3$4/g)
8379 { # MATCH:
8380 # int foo(int new, int class, int (*new)(int));
8381 # unsigned private: 8;
8382 # DO NOT MATCH:
8383 # #pragma GCC visibility push(default)
8384 $CppMode{$Version} = 1;
8385 $Detected = "$1$2$3$4" if(not defined $Detected);
8386 }
8387 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
8388 { # MATCH:
8389 # int delete(...);
8390 # int explicit(...);
8391 # DO NOT MATCH:
8392 # void operator delete(...)
8393 $CppMode{$Version} = 1;
8394 $Detected = "$1$2$3" if(not defined $Detected);
8395 }
8396 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
8397 { # MATCH:
8398 # int bool;
8399 # DO NOT MATCH:
8400 # bool X;
8401 # return *this;
8402 # throw;
8403 $CppMode{$Version} = 1;
8404 $Detected = "$1$2$3" if(not defined $Detected);
8405 }
8406 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
8407 { # MATCH:
8408 # int operator(...);
8409 # DO NOT MATCH:
8410 # int operator()(...);
8411 $CppMode{$Version} = 1;
8412 $Detected = "$1$2$3" if(not defined $Detected);
8413 }
8414 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
8415 { # MATCH:
8416 # int foo(int operator);
8417 # int foo(int operator, int other);
8418 # DO NOT MATCH:
8419 # int operator,(...);
8420 $CppMode{$Version} = 1;
8421 $Detected = "$1$2$3" if(not defined $Detected);
8422 }
8423 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
8424 { # MATCH:
8425 # int foo(gboolean *bool);
8426 # DO NOT MATCH:
8427 # void setTabEnabled(int index, bool);
8428 $CppMode{$Version} = 1;
8429 $Detected = "$1$2$3" if(not defined $Detected);
8430 }
8431 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
8432 { # MATCH:
8433 # int foo(int* this);
8434 # int bar(int this);
8435 # int baz(int throw);
8436 # DO NOT MATCH:
8437 # foo(X, this);
8438 $CppMode{$Version} = 1;
8439 $Detected = "$1$2$3$4" if(not defined $Detected);
8440 }
8441 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
8442 { # MATCH:
8443 # struct template {...};
8444 # extern template foo(...);
8445 $CppMode{$Version} = 1;
8446 $Detected = "$1$2" if(not defined $Detected);
8447 }
8448
8449 if($CppMode{$Version} == 1)
8450 {
8451 if($Debug)
8452 {
8453 $Detected=~s/\A\s+//g;
8454 printMsg("INFO", "Detected code: \"$Detected\"");
8455 }
8456 }
8457
8458 # remove typedef enum NAME NAME;
8459 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
8460 my $N = 0;
8461 while($N<=$#FwdTypedefs-1)
8462 {
8463 my $S = $FwdTypedefs[$N];
8464 if($S eq $FwdTypedefs[$N+1])
8465 {
8466 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008467 $CppMode{$Version} = 1;
8468
8469 if($Debug) {
8470 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
8471 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008472 }
8473 $N+=2;
8474 }
8475
8476 if($CppMode{$Version}==1) {
8477 printMsg("INFO", "Using C++ compatibility mode");
8478 }
8479 }
8480
8481 if($CppMode{$Version}==1
8482 or $MinGWMode{$Version}==1)
8483 {
8484 my $IPath = $TMP_DIR."/dump$Version.i";
8485 writeFile($IPath, $Content);
8486 return $IPath;
8487 }
8488
8489 return undef;
8490}
8491
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008492sub getDump()
8493{
8494 if(not $GCC_PATH) {
8495 exitStatus("Error", "internal error - GCC path is not set");
8496 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008497
8498 my @Headers = keys(%{$Registered_Headers{$Version}});
8499 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
8500
8501 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
8502
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008503 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008504 my $HeaderPath = $TmpHeaderPath;
8505
8506 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008507 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008508 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
8509 {
8510 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008511 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008512 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008513 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008514 foreach my $HPath (@{$Include_Preamble{$Version}}) {
8515 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008516 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008517 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008518 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008519 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
8520 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
8521 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008522 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008523 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008524
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008525 if($ExtraInfo)
8526 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008527 if($IncludeString) {
8528 writeFile($ExtraInfo."/include-string", $IncludeString);
8529 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008530 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
8531 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008532
8533 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
8534 {
8535 my $REDIR = "";
8536 foreach my $P1 (sort @Redirects) {
8537 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
8538 }
8539 writeFile($ExtraInfo."/include-redirect", $REDIR);
8540 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008541 }
8542
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008543 if(not keys(%{$TargetHeaders{$Version}}))
8544 { # Target headers
8545 addTargetHeaders($Version);
8546 }
8547
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008548 # clean memory
8549 %RecursiveIncludes = ();
8550 %Header_Include_Prefix = ();
8551 %Header_Includes = ();
8552
8553 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008554 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008555 delete($Cache{"detect_header_includes"});
8556 delete($Cache{"selectSystemHeader"});
8557
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008558 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008559 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8560 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008561
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008562 if($ExtraInfo)
8563 { # extra information for other tools
8564 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8565 }
8566
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008567 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008568 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008569 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008570
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008571 if($COMMON_LANGUAGE{$Version} eq "C++") {
8572 checkCTags($Pre);
8573 }
8574
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008575 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8576 { # try to correct the preprocessor output
8577 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008578 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008579
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008580 if($COMMON_LANGUAGE{$Version} eq "C++")
8581 { # add classes and namespaces to the dump
8582 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008583 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008584 or $MinGWMode{$Version}==1) {
8585 $CHdump .= " -fpreprocessed";
8586 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008587 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008588 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008589 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008590 chdir($ORIG_DIR);
8591 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8592 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008593 my $Content = readFile($ClassDump);
8594 foreach my $ClassInfo (split(/\n\n/, $Content))
8595 {
8596 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8597 {
8598 my $CName = $1;
8599 next if($CName=~/\A(__|_objc_|_opaque_)/);
8600 $TUnit_NameSpaces{$Version}{$CName} = -1;
8601 if($CName=~/\A[\w:]+\Z/)
8602 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008603 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008604 }
8605 if($CName=~/(\w[\w:]*)::/)
8606 { # namespaces
8607 my $NS = $1;
8608 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8609 $TUnit_NameSpaces{$Version}{$NS} = 1;
8610 }
8611 }
8612 }
8613 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8614 { # read v-tables (advanced approach)
8615 my ($CName, $VTable) = ($1, $2);
8616 $ClassVTable_Content{$Version}{$CName} = $VTable;
8617 }
8618 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008619 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8620 { # add user-defined namespaces
8621 $TUnit_NameSpaces{$Version}{$NS} = 1;
8622 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008623 if($Debug)
8624 { # debug mode
8625 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008626 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008627 }
8628 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008629 }
8630
8631 # add namespaces and classes
8632 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8633 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008634 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008635 }
8636 # some GCC versions don't include class methods to the TU dump by default
8637 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008638 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008639 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8640 {
8641 next if($C_Structure{$CName});
8642 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008643 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008644 if(not $Force and $GCC_44
8645 and $OSgroup eq "linux")
8646 { # optimization for linux with GCC >= 4.4
8647 # disable this code by -force option
8648 if(index($CName, "::")!=-1)
8649 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008650 next;
8651 }
8652 }
8653 else
8654 {
8655 if($CName=~/\A(.+)::[^:]+\Z/
8656 and $TUnit_Classes{$Version}{$1})
8657 { # classes inside other classes
8658 next;
8659 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008660 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008661 if(defined $TUnit_Funcs{$Version}{$CName})
8662 { # the same name for a function and type
8663 next;
8664 }
8665 if(defined $TUnit_Vars{$Version}{$CName})
8666 { # the same name for a variable and type
8667 next;
8668 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008669 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8670 }
8671 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008672 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008673 }
8674 }
8675 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8676 # create TU dump
8677 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008678 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008679 or $MinGWMode{$Version}==1) {
8680 $TUdump .= " -fpreprocessed";
8681 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008682 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008683 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8684 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008685 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008686 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008687 if($?)
8688 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008689 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008690 { # try to recompile
8691 # FIXME: handle other errors and try to recompile
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008692 if($CppMode{$Version}==1
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008693 and index($Errors, "c99_")!=-1
8694 and not defined $CppIncompat)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008695 { # disable c99 mode and try again
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008696 $CppMode{$Version}=-1;
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008697
8698 if($Debug)
8699 {
8700 # printMsg("INFO", $Errors);
8701 }
8702
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008703 printMsg("INFO", "Disabling C++ compatibility mode");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008704 resetLogging($Version);
8705 $TMP_DIR = tempdir(CLEANUP=>1);
8706 return getDump();
8707 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008708 elsif($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008709 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008710 { # add auto preamble headers and try again
8711 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008712 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008713 foreach my $Num (0 .. $#Headers)
8714 {
8715 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008716 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8717 {
8718 push_U($Include_Preamble{$Version}, $Path);
8719 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008720 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008721 }
8722 resetLogging($Version);
8723 $TMP_DIR = tempdir(CLEANUP=>1);
8724 return getDump();
8725 }
8726 elsif($Cpp0xMode{$Version}!=-1
8727 and ($Errors=~/\Q-std=c++0x\E/
8728 or $Errors=~/is not a class or namespace/))
8729 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008730 if(check_gcc($GCC_PATH, "4.6"))
8731 {
8732 $Cpp0xMode{$Version}=-1;
8733 printMsg("INFO", "Enabling c++0x mode");
8734 resetLogging($Version);
8735 $TMP_DIR = tempdir(CLEANUP=>1);
8736 $CompilerOptions{$Version} .= " -std=c++0x";
8737 return getDump();
8738 }
8739 else {
8740 printMsg("WARNING", "Probably c++0x construction detected");
8741 }
8742
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008743 }
8744 elsif($MinGWMode{$Version}==1)
8745 { # disable MinGW mode and try again
8746 $MinGWMode{$Version}=-1;
8747 resetLogging($Version);
8748 $TMP_DIR = tempdir(CLEANUP=>1);
8749 return getDump();
8750 }
8751 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008752 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008753 else {
8754 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008755 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008756 printMsg("ERROR", "some errors occurred when compiling headers");
8757 printErrorLog($Version);
8758 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008759 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008760 }
8761 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008762 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008763 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008764
8765 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8766 return $TUs[0];
8767 }
8768 else
8769 {
8770 my $Msg = "can't compile header(s)";
8771 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8772 $Msg .= "\nDid you install G++?";
8773 }
8774 exitStatus("Cannot_Compile", $Msg);
8775 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008776}
8777
8778sub cmd_file($)
8779{
8780 my $Path = $_[0];
8781 return "" if(not $Path or not -e $Path);
8782 if(my $CmdPath = get_CmdPath("file")) {
8783 return `$CmdPath -b \"$Path\"`;
8784 }
8785 return "";
8786}
8787
8788sub getIncString($$)
8789{
8790 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008791 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008792 my $String = "";
8793 foreach (@{$ArrRef}) {
8794 $String .= " ".inc_opt($_, $Style);
8795 }
8796 return $String;
8797}
8798
8799sub getIncPaths(@)
8800{
8801 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008802 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008803 if($INC_PATH_AUTODETECT{$Version})
8804 { # auto-detecting dependencies
8805 my %Includes = ();
8806 foreach my $HPath (@HeaderPaths)
8807 {
8808 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8809 {
8810 if($Skip_Include_Paths{$Version}{$Dir}) {
8811 next;
8812 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008813 if($SystemRoot)
8814 {
8815 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8816 next;
8817 }
8818 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008819 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008820 }
8821 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008822 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008823 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008824 }
8825 }
8826 else
8827 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008828 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008829 }
8830 return \@IncPaths;
8831}
8832
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008833sub push_U($@)
8834{ # push unique
8835 if(my $Array = shift @_)
8836 {
8837 if(@_)
8838 {
8839 my %Exist = map {$_=>1} @{$Array};
8840 foreach my $Elem (@_)
8841 {
8842 if(not defined $Exist{$Elem})
8843 {
8844 push(@{$Array}, $Elem);
8845 $Exist{$Elem} = 1;
8846 }
8847 }
8848 }
8849 }
8850}
8851
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008852sub callPreprocessor($$$)
8853{
8854 my ($Path, $Inc, $LibVersion) = @_;
8855 return "" if(not $Path or not -f $Path);
8856 my $IncludeString=$Inc;
8857 if(not $Inc) {
8858 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8859 }
8860 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008861 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008862 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008863 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008864}
8865
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008866sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008867{ # native "find" is much faster than File::Find (~6x)
8868 # also the File::Find doesn't support --maxdepth N option
8869 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008870 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008871 return () if(not $Path or not -e $Path);
8872 if($OSgroup eq "windows")
8873 {
8874 my $DirCmd = get_CmdPath("dir");
8875 if(not $DirCmd) {
8876 exitStatus("Not_Found", "can't find \"dir\" command");
8877 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008878 $Path = get_abs_path($Path);
8879 $Path = path_format($Path, $OSgroup);
8880 my $Cmd = $DirCmd." \"$Path\" /B /O";
8881 if($MaxDepth!=1) {
8882 $Cmd .= " /S";
8883 }
8884 if($Type eq "d") {
8885 $Cmd .= " /AD";
8886 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008887 elsif($Type eq "f") {
8888 $Cmd .= " /A-D";
8889 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008890 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008891 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008892 {
8893 if(not $UseRegex)
8894 { # FIXME: how to search file names in MS shell?
8895 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008896 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008897 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008898 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008899 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008900 }
8901 my @AbsPaths = ();
8902 foreach my $File (@Files)
8903 {
8904 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008905 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008906 }
8907 if($Type eq "f" and not -f $File)
8908 { # skip dirs
8909 next;
8910 }
8911 push(@AbsPaths, path_format($File, $OSgroup));
8912 }
8913 if($Type eq "d") {
8914 push(@AbsPaths, $Path);
8915 }
8916 return @AbsPaths;
8917 }
8918 else
8919 {
8920 my $FindCmd = get_CmdPath("find");
8921 if(not $FindCmd) {
8922 exitStatus("Not_Found", "can't find a \"find\" command");
8923 }
8924 $Path = get_abs_path($Path);
8925 if(-d $Path and -l $Path
8926 and $Path!~/\/\Z/)
8927 { # for directories that are symlinks
8928 $Path.="/";
8929 }
8930 my $Cmd = $FindCmd." \"$Path\"";
8931 if($MaxDepth) {
8932 $Cmd .= " -maxdepth $MaxDepth";
8933 }
8934 if($Type) {
8935 $Cmd .= " -type $Type";
8936 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008937 if($Name and not $UseRegex)
8938 { # wildcards
8939 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008940 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008941 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008942 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008943 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8944 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008945 my @Files = split(/\n/, $Res);
8946 if($Name and $UseRegex)
8947 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008948 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008949 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008950 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008951 }
8952}
8953
8954sub unpackDump($)
8955{
8956 my $Path = $_[0];
8957 return "" if(not $Path or not -e $Path);
8958 $Path = get_abs_path($Path);
8959 $Path = path_format($Path, $OSgroup);
8960 my ($Dir, $FileName) = separate_path($Path);
8961 my $UnpackDir = $TMP_DIR."/unpack";
8962 rmtree($UnpackDir);
8963 mkpath($UnpackDir);
8964 if($FileName=~s/\Q.zip\E\Z//g)
8965 { # *.zip
8966 my $UnzipCmd = get_CmdPath("unzip");
8967 if(not $UnzipCmd) {
8968 exitStatus("Not_Found", "can't find \"unzip\" command");
8969 }
8970 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008971 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008972 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008973 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008974 }
8975 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008976 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008977 if(not @Contents) {
8978 exitStatus("Error", "can't extract \'$Path\'");
8979 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008980 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008981 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008982 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008983 { # *.tar.gz
8984 if($OSgroup eq "windows")
8985 { # -xvzf option is not implemented in tar.exe (2003)
8986 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8987 my $TarCmd = get_CmdPath("tar");
8988 if(not $TarCmd) {
8989 exitStatus("Not_Found", "can't find \"tar\" command");
8990 }
8991 my $GzipCmd = get_CmdPath("gzip");
8992 if(not $GzipCmd) {
8993 exitStatus("Not_Found", "can't find \"gzip\" command");
8994 }
8995 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008996 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008997 if($?) {
8998 exitStatus("Error", "can't extract \'$Path\'");
8999 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009000 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009001 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009002 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009003 }
9004 chdir($ORIG_DIR);
9005 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009006 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009007 if(not @Contents) {
9008 exitStatus("Error", "can't extract \'$Path\'");
9009 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009010 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009011 }
9012 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009013 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009014 my $TarCmd = get_CmdPath("tar");
9015 if(not $TarCmd) {
9016 exitStatus("Not_Found", "can't find \"tar\" command");
9017 }
9018 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009019 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009020 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009021 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009022 }
9023 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009024 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009025 if(not @Contents) {
9026 exitStatus("Error", "can't extract \'$Path\'");
9027 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009028 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009029 }
9030 }
9031}
9032
9033sub createArchive($$)
9034{
9035 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009036 if(not $To) {
9037 $To = ".";
9038 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009039 if(not $Path or not -e $Path
9040 or not -d $To) {
9041 return "";
9042 }
9043 my ($From, $Name) = separate_path($Path);
9044 if($OSgroup eq "windows")
9045 { # *.zip
9046 my $ZipCmd = get_CmdPath("zip");
9047 if(not $ZipCmd) {
9048 exitStatus("Not_Found", "can't find \"zip\"");
9049 }
9050 my $Pkg = $To."/".$Name.".zip";
9051 unlink($Pkg);
9052 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04009053 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009054 if($?)
9055 { # cannot allocate memory (or other problems with "zip")
9056 unlink($Path);
9057 exitStatus("Error", "can't pack the ABI dump: ".$!);
9058 }
9059 chdir($ORIG_DIR);
9060 unlink($Path);
9061 return $Pkg;
9062 }
9063 else
9064 { # *.tar.gz
9065 my $TarCmd = get_CmdPath("tar");
9066 if(not $TarCmd) {
9067 exitStatus("Not_Found", "can't find \"tar\"");
9068 }
9069 my $GzipCmd = get_CmdPath("gzip");
9070 if(not $GzipCmd) {
9071 exitStatus("Not_Found", "can't find \"gzip\"");
9072 }
9073 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
9074 unlink($Pkg);
9075 chdir($From);
9076 system($TarCmd, "-czf", $Pkg, $Name);
9077 if($?)
9078 { # cannot allocate memory (or other problems with "tar")
9079 unlink($Path);
9080 exitStatus("Error", "can't pack the ABI dump: ".$!);
9081 }
9082 chdir($ORIG_DIR);
9083 unlink($Path);
9084 return $To."/".$Name.".tar.gz";
9085 }
9086}
9087
9088sub is_header_file($)
9089{
9090 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
9091 return $_[0];
9092 }
9093 return 0;
9094}
9095
9096sub is_not_header($)
9097{
9098 if($_[0]=~/\.\w+\Z/
9099 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
9100 return 1;
9101 }
9102 return 0;
9103}
9104
9105sub is_header($$$)
9106{
9107 my ($Header, $UserDefined, $LibVersion) = @_;
9108 return 0 if(-d $Header);
9109 if(-f $Header) {
9110 $Header = get_abs_path($Header);
9111 }
9112 else
9113 {
9114 if(is_abs($Header))
9115 { # incorrect absolute path
9116 return 0;
9117 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009118 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009119 $Header = $HPath;
9120 }
9121 else
9122 { # can't find header
9123 return 0;
9124 }
9125 }
9126 if($Header=~/\.\w+\Z/)
9127 { # have an extension
9128 return is_header_file($Header);
9129 }
9130 else
9131 {
9132 if($UserDefined==2)
9133 { # specified on the command line
9134 if(cmd_file($Header)!~/HTML|XML/i) {
9135 return $Header;
9136 }
9137 }
9138 elsif($UserDefined)
9139 { # specified in the XML-descriptor
9140 # header file without an extension
9141 return $Header;
9142 }
9143 else
9144 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04009145 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009146 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009147 { # !~/HTML|XML|shared|dynamic/i
9148 return $Header;
9149 }
9150 }
9151 }
9152 return 0;
9153}
9154
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009155sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009156{
9157 my $LibVersion = $_[0];
9158 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
9159 {
9160 my $RegDir = get_dirname($RegHeader);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009161 $TargetHeaders{$LibVersion}{get_filename($RegHeader)} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009162
9163 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
9164 detect_recursive_includes($RegHeader, $LibVersion);
9165 }
9166
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009167 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
9168 {
9169 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009170
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009171 if(familiarDirs($RegDir, $Dir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009172 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
9173 { # in the same directory or included by #include "..."
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009174 $TargetHeaders{$LibVersion}{get_filename($RecInc)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009175 }
9176 }
9177 }
9178}
9179
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009180sub familiarDirs($$)
9181{
9182 my ($D1, $D2) = @_;
9183 if($D1 eq $D2) {
9184 return 1;
9185 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009186
9187 my $U1 = index($D1, "/usr/");
9188 my $U2 = index($D2, "/usr/");
9189
9190 if($U1==0 and $U2!=0) {
9191 return 0;
9192 }
9193
9194 if($U2==0 and $U1!=0) {
9195 return 0;
9196 }
9197
9198 if(index($D2, $D1."/")==0) {
9199 return 1;
9200 }
9201
9202 # /usr/include/DIR
9203 # /home/user/DIR
9204
9205 my $DL = get_depth($D1);
9206
9207 my @Dirs1 = ($D1);
9208 while($DL - get_depth($D1)<=2
9209 and get_depth($D1)>=4
9210 and $D1=~s/[\/\\]+[^\/\\]*?\Z//) {
9211 push(@Dirs1, $D1);
9212 }
9213
9214 my @Dirs2 = ($D2);
9215 while(get_depth($D2)>=4
9216 and $D2=~s/[\/\\]+[^\/\\]*?\Z//) {
9217 push(@Dirs2, $D2);
9218 }
9219
9220 foreach my $P1 (@Dirs1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009221 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009222 foreach my $P2 (@Dirs2)
9223 {
9224
9225 if($P1 eq $P2) {
9226 return 1;
9227 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009228 }
9229 }
9230 return 0;
9231}
9232
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009233sub readHeaders($)
9234{
9235 $Version = $_[0];
9236 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
9237 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009238 if($Debug)
9239 { # debug mode
9240 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009241 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009242 }
9243 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009244}
9245
9246sub prepareTypes($)
9247{
9248 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009249 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009250 { # support for old ABI dumps
9251 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009252 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009253 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009254 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
9255 if($TName=~/\A(\w+)::(\w+)/) {
9256 my ($P1, $P2) = ($1, $2);
9257 if($P1 eq $P2) {
9258 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009259 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009260 else {
9261 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
9262 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009263 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009264 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009265 }
9266 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009267 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009268 { # support for old ABI dumps
9269 # V < 2.5: array size == "number of elements"
9270 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009271 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009272 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009273 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009274 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009275 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009276 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009277 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009278 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009279 $Size *= $Base{"Size"};
9280 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009281 }
9282 else
9283 { # array[] is a pointer
9284 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009285 }
9286 }
9287 }
9288 }
9289 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009290 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009291 { # support for old ABI dumps
9292 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009293 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009294 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009295 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009296 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009297 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009298 my %Type = get_Type($TypeId, $LibVersion);
9299 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
9300 my %Type2 = get_Type($TypeId_2, $V2);
9301 if($Type{"Size"} ne $Type2{"Size"}) {
9302 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009303 }
9304 }
9305 }
9306 }
9307}
9308
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009309sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009310{
9311 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009312
9313 if(not keys(%{$SymbolInfo{$LibVersion}}))
9314 { # check if input is valid
9315 if(not $ExtendedCheck and not $CheckObjectsOnly)
9316 {
9317 if($CheckHeadersOnly) {
9318 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
9319 }
9320 else {
9321 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
9322 }
9323 }
9324 }
9325
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009326 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009327 if(not checkDump(1, "2.10")
9328 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009329 { # different formats
9330 $Remangle = 1;
9331 }
9332 if($CheckHeadersOnly)
9333 { # different languages
9334 if($UserLang)
9335 { # --lang=LANG for both versions
9336 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
9337 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
9338 {
9339 if($UserLang eq "C++")
9340 { # remangle symbols
9341 $Remangle = 1;
9342 }
9343 elsif($UserLang eq "C")
9344 { # remove mangling
9345 $Remangle = -1;
9346 }
9347 }
9348 }
9349 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009350
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009351 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009352 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009353 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009354 { # support for old ABI dumps
9355 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9356 {
9357 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
9358 {
9359 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
9360 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009361 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009362 if(defined $DVal and $DVal ne "")
9363 {
9364 if($TName eq "char") {
9365 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
9366 }
9367 elsif($TName eq "bool") {
9368 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
9369 }
9370 }
9371 }
9372 }
9373 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009374 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009375 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009376 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
9377 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04009378 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009379 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
9380 # + support for old ABI dumps
9381 next;
9382 }
9383 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009384 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009385 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009386 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009387 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009388
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009389 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009390 if(not checkDump(1, "2.12")
9391 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009392 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009393 if($ShortName eq "operator>>")
9394 {
9395 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9396 { # corrected mangling of operator>>
9397 $SRemangle = 1;
9398 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009399 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009400 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9401 {
9402 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
9403 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
9404 { # corrected mangling of const global data
9405 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
9406 # and incorrectly mangled by old ACC versions
9407 $SRemangle = 1;
9408 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009409 }
9410 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009411 if(not $CheckHeadersOnly)
9412 { # support for old ABI dumps
9413 if(not checkDump(1, "2.17")
9414 or not checkDump(2, "2.17"))
9415 {
9416 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9417 {
9418 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9419 {
9420 if(link_symbol($ShortName, $LibVersion, "-Deps"))
9421 {
9422 $MnglName = $ShortName;
9423 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
9424 }
9425 }
9426 }
9427 }
9428 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009429 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009430 { # support for old ABI dumps: some symbols are not mangled in old dumps
9431 # mangle both sets of symbols (old and new)
9432 # NOTE: remangling all symbols by the same mangler
9433 if($MnglName=~/\A_ZN(V|)K/)
9434 { # mangling may be incorrect on old ABI dumps
9435 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009436 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009437 }
9438 if($MnglName=~/\A_ZN(K|)V/)
9439 { # mangling may be incorrect on old ABI dumps
9440 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009441 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009442 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009443 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
9444 or (not $ClassID and $CheckHeadersOnly)
9445 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
9446 { # support for old ABI dumps, GCC >= 4.0
9447 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009448 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009449 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009450 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009451 $MangledNames{$LibVersion}{$MnglName} = 1;
9452 }
9453 }
9454 }
9455 elsif($Remangle==-1)
9456 { # remove mangling
9457 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009458 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009459 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009460 if(not $MnglName) {
9461 next;
9462 }
9463 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
9464 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009465 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9466
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009467 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009468 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009469 { # support for old dumps
9470 # add "Volatile" attribute
9471 if($MnglName=~/_Z(K|)V/) {
9472 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
9473 }
9474 }
9475 # symbol and its symlink have same signatures
9476 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009477 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009478 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009479
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009480 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
9481 {
9482 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9483 if($SymVer{$LibVersion}{$Alias}) {
9484 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9485 }
9486 }
9487
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009488 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009489 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009490 }
9491 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
9492 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
9493 }
9494 if($ExtendedCheck)
9495 { # --ext option
9496 addExtension($LibVersion);
9497 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009498
9499 # clean memory
9500 delete($SymbolInfo{$LibVersion});
9501
9502 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009503 { # detect allocable classes with public exported constructors
9504 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009505 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009506 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009507 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009508 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009509 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
9510 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009511 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009512 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009513 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009514 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009515 $AllocableClass{$LibVersion}{$ClassName} = 1;
9516 }
9517 }
9518 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009519 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009520 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009521 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009522 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009523 if($CheckHeadersOnly)
9524 {
9525 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
9526 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
9527 { # all symbols except non-virtual inline
9528 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
9529 }
9530 }
9531 else {
9532 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009533 }
9534 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009535 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009536 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009537 }
9538 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009539 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009540 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009541 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009542 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009543 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009544 if(defined $Base{"Type"}
9545 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009546 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009547 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009548 if($Name=~/<([^<>\s]+)>/)
9549 {
9550 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
9551 $ReturnedClass{$LibVersion}{$Tid} = 1;
9552 }
9553 }
9554 else {
9555 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
9556 }
9557 }
9558 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009559 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009560 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009561 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009562 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009563 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009564 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009565 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009566 if($Base{"Type"}=~/Struct|Class/)
9567 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009568 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009569 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
9570 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009571 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009572 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009573 }
9574 }
9575 }
9576 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009577
9578 # mapping {short name => symbols}
9579 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009580 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009581 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009582 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009583 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009584 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009585 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009586 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009587 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9588 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009589 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009590 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009591 }
9592 }
9593 }
9594 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009595
9596 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009597 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009598 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009599 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009600 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009601 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
9602 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009603 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009604 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009605 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009606 $ClassNames{$LibVersion}{$TName} = 1;
9607 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009608 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009609 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9610 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009611 }
9612 }
9613 }
9614 }
9615 }
9616}
9617
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009618sub getFirst($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009619{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009620 my ($Tid, $LibVersion) = @_;
9621 if(not $Tid) {
9622 return $Tid;
9623 }
9624
9625 if(my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"})
9626 {
9627 if($TName_Tid{$LibVersion}{$Name}) {
9628 return $TName_Tid{$LibVersion}{$Name};
9629 }
9630 }
9631
9632 return $Tid;
9633}
9634
9635sub register_SymbolUsage($$$)
9636{
9637 my ($InfoId, $UsedType, $LibVersion) = @_;
9638
9639 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9640 if(my $RTid = getFirst($FuncInfo{"Return"}, $LibVersion))
9641 {
9642 register_TypeUsage($RTid, $UsedType, $LibVersion);
9643 $SymbolInfo{$LibVersion}{$InfoId}{"Return"} = $RTid;
9644 }
9645 if(my $FCid = getFirst($FuncInfo{"Class"}, $LibVersion))
9646 {
9647 register_TypeUsage($FCid, $UsedType, $LibVersion);
9648 $SymbolInfo{$LibVersion}{$InfoId}{"Class"} = $FCid;
9649
9650 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
9651 { # register "this" pointer
9652 register_TypeUsage($ThisId, $UsedType, $LibVersion);
9653 }
9654 if(my $ThisId_C = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."const*const", $LibVersion))
9655 { # register "this" pointer (const method)
9656 register_TypeUsage($ThisId_C, $UsedType, $LibVersion);
9657 }
9658 }
9659 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9660 {
9661 if(my $PTid = getFirst($FuncInfo{"Param"}{$PPos}{"type"}, $LibVersion))
9662 {
9663 register_TypeUsage($PTid, $UsedType, $LibVersion);
9664 $FuncInfo{"Param"}{$PPos}{"type"} = $PTid;
9665 }
9666 }
9667 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9668 {
9669 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9670 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
9671 register_TypeUsage($TTid, $UsedType, $LibVersion);
9672 }
9673 }
9674}
9675
9676sub register_TypeUsage($$$)
9677{
9678 my ($TypeId, $UsedType, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009679 if(not $TypeId) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009680 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009681 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009682 if($UsedType->{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009683 { # already registered
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009684 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009685 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009686
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009687 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009688 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009689 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009690 if(my $NS = $TInfo{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009691 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009692 if(my $NSTid = $TName_Tid{$LibVersion}{$NS}) {
9693 register_TypeUsage($NSTid, $UsedType, $LibVersion);
9694 }
9695 }
9696
9697 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|Func|MethodPtr|FieldPtr|Enum)\Z/)
9698 {
9699 $UsedType->{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009700 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009701 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009702 foreach my $BaseId (keys(%{$TInfo{"Base"}})) {
9703 register_TypeUsage($BaseId, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009704 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009705 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9706 {
9707 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9708 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009709 register_TypeUsage($TTid, $UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009710 }
9711 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009712 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009713 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009714 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009715 if(my $MTid = getFirst($TInfo{"Memb"}{$Memb_Pos}{"type"}, $LibVersion))
9716 {
9717 register_TypeUsage($MTid, $UsedType, $LibVersion);
9718 $TInfo{"Memb"}{$Memb_Pos}{"type"} = $MTid;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009719 }
9720 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009721 if($TInfo{"Type"} eq "FuncPtr"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009722 or $TInfo{"Type"} eq "MethodPtr"
9723 or $TInfo{"Type"} eq "Func")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009724 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009725 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009726 register_TypeUsage($RTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009727 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009728 foreach my $PPos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009729 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009730 if(my $PTid = $TInfo{"Param"}{$PPos}{"type"}) {
9731 register_TypeUsage($PTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009732 }
9733 }
9734 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009735 if($TInfo{"Type"} eq "FieldPtr")
9736 {
9737 if(my $RTid = $TInfo{"Return"}) {
9738 register_TypeUsage($RTid, $UsedType, $LibVersion);
9739 }
9740 if(my $CTid = $TInfo{"Class"}) {
9741 register_TypeUsage($CTid, $UsedType, $LibVersion);
9742 }
9743 }
9744 if($TInfo{"Type"} eq "MethodPtr")
9745 {
9746 if(my $CTid = $TInfo{"Class"}) {
9747 register_TypeUsage($CTid, $UsedType, $LibVersion);
9748 }
9749 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009750 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009751 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009752 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009753 $UsedType->{$TypeId} = 1;
9754 if(my $BTid = getFirst($TInfo{"BaseType"}, $LibVersion))
9755 {
9756 register_TypeUsage($BTid, $UsedType, $LibVersion);
9757 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $BTid;
9758 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009759 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009760 else
9761 { # Intrinsic, TemplateParam, TypeName, SizeOf, etc.
9762 $UsedType->{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009763 }
9764 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009765}
9766
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009767sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009768{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009769 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9770
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009771 if($Level eq "Dump")
9772 {
9773 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9774 { # TODO: check if this symbol is from
9775 # base classes of other target symbols
9776 return 1;
9777 }
9778 }
9779
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009780 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9781 { # stdc++ interfaces
9782 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009783 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009784
9785 my $Target = 0;
9786 if(my $Header = $SInfo->{"Header"}) {
9787 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9788 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009789 if($ExtendedCheck)
9790 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009791 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009792 $Target = 1;
9793 }
9794 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009795 if($CheckHeadersOnly or $Level eq "Source")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009796 {
9797 if($Target)
9798 {
9799 if($Level eq "Dump")
9800 { # dumped
9801 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009802 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009803 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009804 return 1;
9805 }
9806 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009807 else {
9808 return 1;
9809 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009810 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009811 elsif($Level eq "Source")
9812 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009813 return 1;
9814 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009815 elsif($Level eq "Binary")
9816 { # checked
9817 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9818 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9819 return 1;
9820 }
9821 }
9822 }
9823 }
9824 else
9825 { # library is available
9826 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9827 { # exported symbols
9828 return 1;
9829 }
9830 if($Level eq "Dump")
9831 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009832 if($BinaryOnly)
9833 {
9834 if($SInfo->{"Data"})
9835 {
9836 if($Target) {
9837 return 1;
9838 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009839 }
9840 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009841 else
9842 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009843 if($Target) {
9844 return 1;
9845 }
9846 }
9847 }
9848 elsif($Level eq "Source")
9849 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009850 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
9851 or isInLineInst($Symbol, $SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009852 { # skip LOCAL symbols
9853 if($Target) {
9854 return 1;
9855 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009856 }
9857 }
9858 elsif($Level eq "Binary")
9859 { # checked
9860 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9861 {
9862 if($Target) {
9863 return 1;
9864 }
9865 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009866 }
9867 }
9868 return 0;
9869}
9870
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009871sub cleanDump($)
9872{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009873 my $LibVersion = $_[0];
9874 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9875 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009876 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}}))
9877 {
9878 delete($SymbolInfo{$LibVersion}{$InfoId});
9879 next;
9880 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009881 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009882 if(not $MnglName)
9883 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009884 delete($SymbolInfo{$LibVersion}{$InfoId});
9885 next;
9886 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009887 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009888 if(not $ShortName)
9889 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009890 delete($SymbolInfo{$LibVersion}{$InfoId});
9891 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009892 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009893 if($MnglName eq $ShortName)
9894 { # remove duplicate data
9895 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009896 }
9897 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9898 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9899 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009900 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9901 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9902 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04009903 delete($SymbolInfo{$LibVersion}{$InfoId}{"Type"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009904 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009905 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009906 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009907 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}}))
9908 {
9909 delete($TypeInfo{$LibVersion}{$Tid});
9910 next;
9911 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009912 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009913 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009914 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009915 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9916 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9917 }
9918 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009919 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9920 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9921 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009922 }
9923}
9924
9925sub selectType($$)
9926{
9927 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009928
9929 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9930 {
9931 if(defined $TypeInfo{$LibVersion}{$Dupl})
9932 {
9933 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9934 { # duplicate
9935 return 0;
9936 }
9937 }
9938 }
9939
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009940 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
9941 {
9942 if(not isBuiltIn($THeader))
9943 {
9944 if($TypeInfo{$LibVersion}{$Tid}{"Type"}=~/Class|Struct|Union|Enum|Typedef/)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009945 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009946 if(not isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"}))
9947 {
9948 if(is_target_header($THeader, $LibVersion))
9949 { # from target headers
9950 if(not selfTypedef($Tid, $LibVersion)) {
9951 return 1;
9952 }
9953 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009954 }
9955 }
9956 }
9957 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009958 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009959}
9960
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009961sub remove_Unused($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009962{ # remove unused data types from the ABI dump
9963 my ($LibVersion, $Kind) = @_;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009964
9965 my %UsedType = ();
9966
9967 foreach my $InfoId (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009968 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009969 register_SymbolUsage($InfoId, \%UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009970 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009971 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009972 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009973 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009974 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009975 next;
9976 }
9977
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009978 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009979 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009980 if(selectType($Tid, $LibVersion))
9981 {
9982 my %Tree = ();
9983 register_TypeUsage($Tid, \%Tree, $LibVersion);
9984
9985 my $Tmpl = 0;
9986 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9987 {
9988 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9989 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9990 {
9991 $Tmpl = 1;
9992 last;
9993 }
9994 }
9995 if(not $Tmpl)
9996 {
9997 foreach (keys(%Tree)) {
9998 $UsedType{$_} = 1;
9999 }
10000 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010001 }
10002 }
10003 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040010004
10005 my %Delete = ();
10006
10007 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010008 { # remove unused types
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040010009 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010010 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010011 next;
10012 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040010013
10014 if($Kind eq "Extra")
10015 {
10016 my %Tree = ();
10017 register_TypeUsage($Tid, \%Tree, $LibVersion);
10018
10019 foreach (sort {int($a)<=>int($b)} keys(%Tree))
10020 {
10021 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
10022 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
10023 {
10024 $Delete{$Tid} = 1;
10025 last;
10026 }
10027 }
10028 }
10029 else
10030 {
10031 # remove type
10032 delete($TypeInfo{$LibVersion}{$Tid});
10033 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010034 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010035
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040010036 if($Kind eq "Extra")
10037 { # remove duplicates
10038 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
10039 {
10040 if($UsedType{$Tid})
10041 { # All & Extended
10042 next;
10043 }
10044
10045 my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10046
10047 if($TName_Tid{$LibVersion}{$Name} ne $Tid) {
10048 delete($TypeInfo{$LibVersion}{$Tid});
10049 }
10050 }
10051 }
10052
10053 foreach my $Tid (keys(%Delete))
10054 {
10055 delete($TypeInfo{$LibVersion}{$Tid});
10056 }
10057}
10058
10059sub check_Completeness($$)
10060{
10061 my ($Info, $LibVersion) = @_;
10062
10063 # data types
10064 if(defined $Info->{"Memb"})
10065 {
10066 foreach my $Pos (keys(%{$Info->{"Memb"}}))
10067 {
10068 if(defined $Info->{"Memb"}{$Pos}{"type"}) {
10069 check_TypeInfo($Info->{"Memb"}{$Pos}{"type"}, $LibVersion);
10070 }
10071 }
10072 }
10073 if(defined $Info->{"Base"})
10074 {
10075 foreach my $Bid (keys(%{$Info->{"Base"}})) {
10076 check_TypeInfo($Bid, $LibVersion);
10077 }
10078 }
10079 if(defined $Info->{"BaseType"}) {
10080 check_TypeInfo($Info->{"BaseType"}, $LibVersion);
10081 }
10082 if(defined $Info->{"TParam"})
10083 {
10084 foreach my $Pos (keys(%{$Info->{"TParam"}}))
10085 {
10086 my $TName = $Info->{"TParam"}{$Pos}{"name"};
10087 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) {
10088 next;
10089 }
10090 if($TName eq "_BoolType") {
10091 next;
10092 }
10093 if($TName=~/\Asizeof\(/) {
10094 next;
10095 }
10096 if(my $Tid = $TName_Tid{$LibVersion}{$TName}) {
10097 check_TypeInfo($Tid, $LibVersion);
10098 }
10099 else
10100 {
10101 if(defined $Debug) {
10102 printMsg("WARNING", "missed type $TName");
10103 }
10104 }
10105 }
10106 }
10107
10108 # symbols
10109 if(defined $Info->{"Param"})
10110 {
10111 foreach my $Pos (keys(%{$Info->{"Param"}}))
10112 {
10113 if(defined $Info->{"Param"}{$Pos}{"type"}) {
10114 check_TypeInfo($Info->{"Param"}{$Pos}{"type"}, $LibVersion);
10115 }
10116 }
10117 }
10118 if(defined $Info->{"Return"}) {
10119 check_TypeInfo($Info->{"Return"}, $LibVersion);
10120 }
10121 if(defined $Info->{"Class"}) {
10122 check_TypeInfo($Info->{"Class"}, $LibVersion);
10123 }
10124}
10125
10126sub check_TypeInfo($$)
10127{
10128 my ($Tid, $LibVersion) = @_;
10129
10130 if(defined $CheckedTypeInfo{$LibVersion}{$Tid}) {
10131 return;
10132 }
10133 $CheckedTypeInfo{$LibVersion}{$Tid} = 1;
10134
10135 if(defined $TypeInfo{$LibVersion}{$Tid})
10136 {
10137 if(not $TypeInfo{$LibVersion}{$Tid}{"Name"}) {
10138 printMsg("ERROR", "missed type name ($Tid)");
10139 }
10140 check_Completeness($TypeInfo{$LibVersion}{$Tid}, $LibVersion);
10141 }
10142 else {
10143 printMsg("ERROR", "missed type id $Tid");
10144 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010145}
10146
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010147sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010148{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010149 my ($TypeId, $LibVersion) = @_;
10150 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010151 if($Type{"Type"} eq "Typedef")
10152 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010153 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010154 if($Base{"Type"}=~/Class|Struct/)
10155 {
10156 if($Type{"Name"} eq $Base{"Name"}) {
10157 return 1;
10158 }
10159 elsif($Type{"Name"}=~/::(\w+)\Z/)
10160 {
10161 if($Type{"Name"} eq $Base{"Name"}."::".$1)
10162 { # QPointer<QWidget>::QPointer
10163 return 1;
10164 }
10165 }
10166 }
10167 }
10168 return 0;
10169}
10170
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010171sub addExtension($)
10172{
10173 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010174 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010175 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010176 if(selectType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010177 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010178 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10179 $TName=~s/\A(struct|union|class|enum) //;
10180 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010181
10182 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
10183 "Header" => "extended.h",
10184 "ShortName" => $Symbol,
10185 "MnglName" => $Symbol,
10186 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
10187 );
10188
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010189 $ExtendedSymbols{$Symbol} = 1;
10190 $CheckedSymbols{"Binary"}{$Symbol} = 1;
10191 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010192 }
10193 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010194 $ExtendedSymbols{"external_func_0"} = 1;
10195 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
10196 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010197}
10198
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010199sub findMethod($$$)
10200{
10201 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010202 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010203 {
10204 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
10205 return $VirtMethodInClass;
10206 }
10207 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
10208 return $VirtMethodInBaseClasses;
10209 }
10210 }
10211 return "";
10212}
10213
10214sub findMethod_Class($$$)
10215{
10216 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010217 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010218 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
10219 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
10220 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
10221 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10222 { # search for interface with the same parameters suffix (overridden)
10223 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
10224 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010225 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
10226 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010227 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
10228 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010229 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
10230 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
10231 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
10232 return $Candidate;
10233 }
10234 }
10235 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010236 else
10237 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010238 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
10239 return $Candidate;
10240 }
10241 }
10242 }
10243 }
10244 return "";
10245}
10246
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010247sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010248{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010249 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010250 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010251 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010252 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
10253 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010254 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010255 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010256 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010257 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
10258 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010259 { # pure virtual D2-destructors are marked as "virt" in the dump
10260 # virtual D2-destructors are NOT marked as "virt" in the dump
10261 # both destructors are not presented in the v-table
10262 next;
10263 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010264 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010265 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
10266 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010267 }
10268}
10269
10270sub registerOverriding($)
10271{
10272 my $LibVersion = $_[0];
10273 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010274 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010275 foreach my $ClassName (@Classes)
10276 {
10277 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10278 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010279 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
10280 { # pure virtuals
10281 next;
10282 }
10283 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
10284 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010285 {
10286 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
10287 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
10288 { # both overridden virtual methods
10289 # and implemented pure virtual methods
10290 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
10291 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
10292 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
10293 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010294 }
10295 }
10296 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
10297 delete($VirtualTable{$LibVersion}{$ClassName});
10298 }
10299 }
10300}
10301
10302sub setVirtFuncPositions($)
10303{
10304 my $LibVersion = $_[0];
10305 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
10306 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010307 my ($Num, $Rel) = (1, 0);
10308
10309 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010310 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010311 if($UsedDump{$LibVersion}{"DWARF"}) {
10312 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
10313 }
10314 else {
10315 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
10316 }
10317 foreach my $VirtFunc (@Funcs)
10318 {
10319 if($UsedDump{$LibVersion}{"DWARF"}) {
10320 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
10321 }
10322 else {
10323 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
10324 }
10325
10326 # set relative positions
10327 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
10328 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
10329 { # relative position excluding added and removed virtual functions
10330 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
10331 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
10332 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
10333 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010334 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010335 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010336 }
10337 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010338 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010339 {
10340 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010341 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010342 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010343 }
10344 }
10345}
10346
10347sub get_sub_classes($$$)
10348{
10349 my ($ClassId, $LibVersion, $Recursive) = @_;
10350 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
10351 my @Subs = ();
10352 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10353 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010354 if($Recursive)
10355 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010356 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
10357 push(@Subs, $SubSubId);
10358 }
10359 }
10360 push(@Subs, $SubId);
10361 }
10362 return @Subs;
10363}
10364
10365sub get_base_classes($$$)
10366{
10367 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010368 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010369 return () if(not defined $ClassType{"Base"});
10370 my @Bases = ();
10371 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
10372 keys(%{$ClassType{"Base"}}))
10373 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010374 if($Recursive)
10375 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010376 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
10377 push(@Bases, $SubBaseId);
10378 }
10379 }
10380 push(@Bases, $BaseId);
10381 }
10382 return @Bases;
10383}
10384
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010385sub getVTable_Model($$)
10386{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010387 my ($ClassId, $LibVersion) = @_;
10388 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10389 my @Elements = ();
10390 foreach my $BaseId (@Bases, $ClassId)
10391 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010392 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010393 {
10394 if(defined $VirtualTable{$LibVersion}{$BName})
10395 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010396 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
10397 if($UsedDump{$LibVersion}{"DWARF"}) {
10398 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
10399 }
10400 else {
10401 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
10402 }
10403 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010404 push(@Elements, $VFunc);
10405 }
10406 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010407 }
10408 }
10409 return @Elements;
10410}
10411
10412sub getVShift($$)
10413{
10414 my ($ClassId, $LibVersion) = @_;
10415 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10416 my $VShift = 0;
10417 foreach my $BaseId (@Bases)
10418 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010419 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010420 {
10421 if(defined $VirtualTable{$LibVersion}{$BName}) {
10422 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
10423 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010424 }
10425 }
10426 return $VShift;
10427}
10428
10429sub getShift($$)
10430{
10431 my ($ClassId, $LibVersion) = @_;
10432 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
10433 my $Shift = 0;
10434 foreach my $BaseId (@Bases)
10435 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010436 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010437 {
10438 if($Size!=1)
10439 { # not empty base class
10440 $Shift+=$Size;
10441 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010442 }
10443 }
10444 return $Shift;
10445}
10446
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010447sub getVTable_Size($$)
10448{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010449 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010450 my $Size = 0;
10451 # three approaches
10452 if(not $Size)
10453 { # real size
10454 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
10455 $Size = keys(%VTable);
10456 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010457 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010458 if(not $Size)
10459 { # shared library symbol size
10460 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
10461 $Size /= $WORD_SIZE{$LibVersion};
10462 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010463 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010464 if(not $Size)
10465 { # model size
10466 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
10467 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
10468 }
10469 }
10470 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010471}
10472
10473sub isCopyingClass($$)
10474{
10475 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010476 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010477}
10478
10479sub isLeafClass($$)
10480{
10481 my ($ClassId, $LibVersion) = @_;
10482 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
10483}
10484
10485sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010486{ # check structured type for public fields
10487 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010488}
10489
10490sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010491{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010492 my ($TypePtr, $Skip, $Start, $End) = @_;
10493 return 0 if(not $TypePtr);
10494 if($End==-1) {
10495 $End = keys(%{$TypePtr->{"Memb"}})-1;
10496 }
10497 foreach my $MemPos (keys(%{$TypePtr->{"Memb"}}))
10498 {
10499 if($Skip and $Skip->{$MemPos})
10500 { # skip removed/added fields
10501 next;
10502 }
10503 if(int($MemPos)>=$Start and int($MemPos)<=$End)
10504 {
10505 if(isPublic($TypePtr, $MemPos)) {
10506 return ($MemPos+1);
10507 }
10508 }
10509 }
10510 return 0;
10511}
10512
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010513sub isReserved($)
10514{ # reserved fields == private
10515 my $MName = $_[0];
10516 if($MName=~/reserved|padding|f_spare/i) {
10517 return 1;
10518 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010519 if($MName=~/\A[_]*(spare|pad|unused)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010520 return 1;
10521 }
10522 if($MName=~/(pad\d+)/i) {
10523 return 1;
10524 }
10525 return 0;
10526}
10527
10528sub isPublic($$)
10529{
10530 my ($TypePtr, $FieldPos) = @_;
10531 return 0 if(not $TypePtr);
10532 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
10533 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
10534 if(not $TypePtr->{"Memb"}{$FieldPos}{"access"})
10535 { # by name in C language
10536 # FIXME: add other methods to detect private members
10537 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
10538 if($MName=~/priv|abidata|parent_object/i)
10539 { # C-styled private data
10540 return 0;
10541 }
10542 if(lc($MName) eq "abi")
10543 { # ABI information/reserved field
10544 return 0;
10545 }
10546 if(isReserved($MName))
10547 { # reserved fields
10548 return 0;
10549 }
10550 return 1;
10551 }
10552 elsif($TypePtr->{"Memb"}{$FieldPos}{"access"} ne "private")
10553 { # by access in C++ language
10554 return 1;
10555 }
10556 return 0;
10557}
10558
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010559sub getVTable_Real($$)
10560{
10561 my ($ClassName, $LibVersion) = @_;
10562 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
10563 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010564 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010565 if(defined $Type{"VTable"}) {
10566 return %{$Type{"VTable"}};
10567 }
10568 }
10569 return ();
10570}
10571
10572sub cmpVTables($)
10573{
10574 my $ClassName = $_[0];
10575 my $Res = cmpVTables_Real($ClassName, 1);
10576 if($Res==-1) {
10577 $Res = cmpVTables_Model($ClassName);
10578 }
10579 return $Res;
10580}
10581
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010582sub cmpVTables_Model($)
10583{
10584 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010585 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010586 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010587 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010588 return 1;
10589 }
10590 }
10591 return 0;
10592}
10593
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010594sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010595{
10596 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010597 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
10598 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010599 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010600 my %VTable_Old = getVTable_Real($ClassName, 1);
10601 my %VTable_New = getVTable_Real($ClassName, 2);
10602 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010603 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010604 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010605 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010606 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010607 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
10608 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010609 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010610 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010611 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010612 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010613 my $Entry1 = $VTable_Old{$Offset};
10614 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010615 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010616 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010617 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010618 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010619 $Entry1 = simpleVEntry($Entry1);
10620 $Entry2 = simpleVEntry($Entry2);
10621 if($Entry1 ne $Entry2)
10622 { # register as changed
10623 if($Entry1=~/::([^:]+)\Z/)
10624 {
10625 my $M1 = $1;
10626 if($Entry2=~/::([^:]+)\Z/)
10627 {
10628 my $M2 = $1;
10629 if($M1 eq $M2)
10630 { # overridden
10631 next;
10632 }
10633 }
10634 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010635 if(differentDumps("G"))
10636 {
10637 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
10638 {
10639 # GCC 4.6.1: -0x00000000000000010
10640 # GCC 4.7.0: -16
10641 next;
10642 }
10643 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010644 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010645 }
10646 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010647 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010648}
10649
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010650sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010651{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010652 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010653 foreach my $ClassName (keys(%{$VirtualTable{1}}))
10654 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010655 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010656 { # already registered
10657 next;
10658 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010659 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010660 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010661 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010662 foreach my $Symbol (@Affected)
10663 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010664 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010665 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010666 "Target"=>$ClassName);
10667 }
10668 }
10669 }
10670}
10671
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010672sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010673{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010674 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010675 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010676 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010677 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010678 next if(not $ClassId);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010679 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010680 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010681 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010682 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010683 if($TName_Tid{1}{$ClassName}
10684 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010685 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010686 if(defined $CompleteSignature{1}{$Symbol}
10687 and $CompleteSignature{1}{$Symbol}{"Virt"})
10688 { # override some method in v.1
10689 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010690 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010691 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010692 }
10693 }
10694 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010695 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010696 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010697 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010698 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010699 if($TName_Tid{2}{$ClassName}
10700 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010701 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010702 if(defined $CompleteSignature{2}{$Symbol}
10703 and $CompleteSignature{2}{$Symbol}{"Virt"})
10704 { # override some method in v.2
10705 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010706 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010707 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010708 }
10709 }
10710 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010711 if($Level eq "Binary")
10712 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010713 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010714 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
10715 { # check replacements, including pure virtual methods
10716 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
10717 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010718 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010719 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
10720 if($AddedPos==$RemovedPos)
10721 {
10722 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
10723 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
10724 last; # other methods will be reported as "added" or "removed"
10725 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010726 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010727 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
10728 {
10729 if(lc($AddedVFunc) eq lc($RemovedVFunc))
10730 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010731 next;
10732 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010733 my $ProblemType = "Virtual_Replacement";
10734 my @Affected = ($RemovedVFunc);
10735 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10736 { # pure methods
10737 if(not isUsedClass($ClassId, 1, $Level))
10738 { # not a parameter of some exported method
10739 next;
10740 }
10741 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010742
10743 # affected all methods (both virtual and non-virtual ones)
10744 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
10745 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010746 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010747 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010748 foreach my $AffectedInt (@Affected)
10749 {
10750 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
10751 { # affected exported methods only
10752 next;
10753 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010754 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
10755 next;
10756 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010757 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10758 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010759 "Target"=>get_Signature($AddedVFunc, 2),
10760 "Old_Value"=>get_Signature($RemovedVFunc, 1));
10761 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010762 }
10763 }
10764 }
10765 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010766 if(not checkDump(1, "2.0")
10767 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010768 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010769 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010770 return;
10771 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010772 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010773 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010774 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010775 next if(not $ClassId_Old);
10776 if(not isCreatable($ClassId_Old, 1))
10777 { # skip classes without public constructors (including auto-generated)
10778 # example: class has only a private exported or private inline constructor
10779 next;
10780 }
10781 if($ClassName=~/>/)
10782 { # skip affected template instances
10783 next;
10784 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010785 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010786 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010787 if(not $ClassId_New) {
10788 next;
10789 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010790 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010791 if($Class_New{"Type"}!~/Class|Struct/)
10792 { # became typedef
10793 if($Level eq "Binary") {
10794 next;
10795 }
10796 if($Level eq "Source")
10797 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010798 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010799 if($Class_New{"Type"}!~/Class|Struct/) {
10800 next;
10801 }
10802 $ClassId_New = $Class_New{"Tid"};
10803 }
10804 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010805 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10806 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 +040010807
10808 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10809 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10810
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010811 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010812 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10813 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010814 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10815 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010816 my $Shift_Old = getShift($ClassId_Old, 1);
10817 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010818 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010819 my ($Added, $Removed) = (0, 0);
10820 my @StableBases_Old = ();
10821 foreach my $BaseId (@Bases_Old)
10822 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010823 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010824 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010825 push(@StableBases_Old, $BaseId);
10826 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010827 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010828 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010829 { # removed base
10830 # excluding namespace::SomeClass to SomeClass renaming
10831 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010832 if($Level eq "Binary")
10833 { # Binary-level
10834 if($Shift_Old ne $Shift_New)
10835 { # affected fields
10836 if(havePubFields(\%Class_Old)) {
10837 $ProblemKind .= "_And_Shift";
10838 }
10839 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10840 $ProblemKind .= "_And_Size";
10841 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010842 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010843 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10844 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010845 { # affected v-table
10846 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010847 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010848 }
10849 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010850 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010851 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10852 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010853 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10854 {
10855 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10856 if($ProblemKind=~/VTable/) {
10857 $VTableChanged_M{$SubName}=1;
10858 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010859 }
10860 }
10861 foreach my $Interface (@Affected)
10862 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010863 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10864 next;
10865 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010866 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010867 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010868 "Target"=>$BaseName,
10869 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10870 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10871 "Shift"=>abs($Shift_New-$Shift_Old) );
10872 }
10873 $Removed+=1;
10874 }
10875 }
10876 my @StableBases_New = ();
10877 foreach my $BaseId (@Bases_New)
10878 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010879 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010880 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010881 push(@StableBases_New, $BaseId);
10882 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010883 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010884 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010885 { # added base
10886 # excluding namespace::SomeClass to SomeClass renaming
10887 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010888 if($Level eq "Binary")
10889 { # Binary-level
10890 if($Shift_Old ne $Shift_New)
10891 { # affected fields
10892 if(havePubFields(\%Class_Old)) {
10893 $ProblemKind .= "_And_Shift";
10894 }
10895 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10896 $ProblemKind .= "_And_Size";
10897 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010898 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010899 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10900 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010901 { # affected v-table
10902 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010903 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010904 }
10905 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010906 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010907 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10908 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010909 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10910 {
10911 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10912 if($ProblemKind=~/VTable/) {
10913 $VTableChanged_M{$SubName}=1;
10914 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010915 }
10916 }
10917 foreach my $Interface (@Affected)
10918 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010919 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10920 next;
10921 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010922 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010923 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010924 "Target"=>$BaseName,
10925 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10926 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10927 "Shift"=>abs($Shift_New-$Shift_Old) );
10928 }
10929 $Added+=1;
10930 }
10931 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010932 if($Level eq "Binary")
10933 { # Binary-level
10934 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010935 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10936 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010937 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010938 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010939 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010940 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010941 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010942 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10943 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010944 if($NewPos!=$OldPos)
10945 { # changed position of the base class
10946 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010947 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010948 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10949 next;
10950 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010951 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10952 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010953 "Target"=>$BaseName,
10954 "Old_Value"=>$OldPos-1,
10955 "New_Value"=>$NewPos-1 );
10956 }
10957 }
10958 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10959 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10960 { # became non-virtual base
10961 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10962 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010963 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10964 next;
10965 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010966 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10967 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010968 "Target"=>$BaseName );
10969 }
10970 }
10971 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10972 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10973 { # became virtual base
10974 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10975 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010976 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10977 next;
10978 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010979 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10980 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010981 "Target"=>$BaseName );
10982 }
10983 }
10984 }
10985 }
10986 # detect size changes in base classes
10987 if($Shift_Old!=$Shift_New)
10988 { # size of allocable class
10989 foreach my $BaseId (@StableBases_Old)
10990 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010991 my %BaseType = get_Type($BaseId, 1);
10992 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010993 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010994 if($Size_Old ne $Size_New
10995 and $Size_Old and $Size_New)
10996 {
10997 my $ProblemType = "";
10998 if(isCopyingClass($BaseId, 1)) {
10999 $ProblemType = "Size_Of_Copying_Class";
11000 }
11001 elsif($AllocableClass{1}{$BaseType{"Name"}})
11002 {
11003 if($Size_New>$Size_Old)
11004 { # increased size
11005 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011006 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011007 else
11008 { # decreased size
11009 $ProblemType = "Size_Of_Allocable_Class_Decreased";
11010 if(not havePubFields(\%Class_Old))
11011 { # affected class has no public members
11012 next;
11013 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011014 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011015 }
11016 next if(not $ProblemType);
11017 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
11018 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011019 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
11020 next;
11021 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011022 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
11023 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011024 "Target"=>$BaseType{"Name"},
11025 "Old_Size"=>$Size_Old*$BYTE_SIZE,
11026 "New_Size"=>$Size_New*$BYTE_SIZE );
11027 }
11028 }
11029 }
11030 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011031 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011032 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011033 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011034 { # compare virtual tables size in base classes
11035 my $VShift_Old = getVShift($ClassId_Old, 1);
11036 my $VShift_New = getVShift($ClassId_New, 2);
11037 if($VShift_Old ne $VShift_New)
11038 { # changes in the base class or changes in the list of base classes
11039 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
11040 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
11041 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011042 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011043 foreach my $BaseId (@AllBases_Old)
11044 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011045 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011046 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011047 { # lost base
11048 next;
11049 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011050 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
11051 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011052 if($VSize_Old!=$VSize_New)
11053 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011054 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011055 { # TODO: affected non-virtual methods?
11056 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011057 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
11058 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011059 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011060 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011061 { # skip interfaces that have not changed the absolute virtual position
11062 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011063 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011064 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
11065 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011066 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011067 $VTableChanged_M{$BaseType{"Name"}} = 1;
11068 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011069 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
11070 { # the reason of the layout change: added virtual functions
11071 next if($VirtualReplacement{$VirtFunc});
11072 my $ProblemType = "Added_Virtual_Method";
11073 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
11074 $ProblemType = "Added_Pure_Virtual_Method";
11075 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011076 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011077 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011078 "Target"=>get_Signature($VirtFunc, 2) );
11079 }
11080 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
11081 { # the reason of the layout change: removed virtual functions
11082 next if($VirtualReplacement{$VirtFunc});
11083 my $ProblemType = "Removed_Virtual_Method";
11084 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
11085 $ProblemType = "Removed_Pure_Virtual_Method";
11086 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011087 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011088 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011089 "Target"=>get_Signature($VirtFunc, 1) );
11090 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011091 }
11092 }
11093 }
11094 }
11095 }
11096 }
11097 }
11098}
11099
11100sub isCreatable($$)
11101{
11102 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011103 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011104 or isCopyingClass($ClassId, $LibVersion)) {
11105 return 1;
11106 }
11107 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
11108 { # Fix for incomplete data: if this class has
11109 # a base class then it should also has a constructor
11110 return 1;
11111 }
11112 if($ReturnedClass{$LibVersion}{$ClassId})
11113 { # returned by some method of this class
11114 # or any other class
11115 return 1;
11116 }
11117 return 0;
11118}
11119
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011120sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011121{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011122 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011123 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
11124 { # parameter of some exported method
11125 return 1;
11126 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011127 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
11128 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011129 { # method from target class
11130 return 1;
11131 }
11132 return 0;
11133}
11134
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011135sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011136{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011137 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011138 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011139 # - virtual
11140 # - pure-virtual
11141 # - non-virtual
11142 if($CompleteSignature{1}{$Interface}{"Data"})
11143 { # global data is not affected
11144 return;
11145 }
11146 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011147 if(not $Class_Id) {
11148 return;
11149 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011150 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011151 if(cmpVTables_Real($CName, 1)==0)
11152 { # no changes
11153 return;
11154 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011155 $CheckedTypes{$Level}{$CName} = 1;
11156 if($Level eq "Binary")
11157 { # Binary-level
11158 if($CompleteSignature{1}{$Interface}{"PureVirt"}
11159 and not isUsedClass($Class_Id, 1, $Level))
11160 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011161 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011162 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011163 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011164 }
11165 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
11166 {
11167 if(defined $VirtualTable{2}{$CName}{$Func}
11168 and defined $CompleteSignature{2}{$Func})
11169 {
11170 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
11171 and $CompleteSignature{2}{$Func}{"PureVirt"})
11172 { # became pure virtual
11173 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
11174 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011175 "Target"=>get_Signature_M($Func, 1) );
11176 $VTableChanged_M{$CName} = 1;
11177 }
11178 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
11179 and not $CompleteSignature{2}{$Func}{"PureVirt"})
11180 { # became non-pure virtual
11181 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
11182 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011183 "Target"=>get_Signature_M($Func, 1) );
11184 $VTableChanged_M{$CName} = 1;
11185 }
11186 }
11187 }
11188 if($Level eq "Binary")
11189 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011190 # check virtual table structure
11191 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
11192 {
11193 next if($Interface eq $AddedVFunc);
11194 next if($VirtualReplacement{$AddedVFunc});
11195 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
11196 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
11197 { # pure virtual methods affect all others (virtual and non-virtual)
11198 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011199 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011200 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011201 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011202 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011203 elsif(not defined $VirtualTable{1}{$CName}
11204 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011205 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011206 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011207 { # became polymorphous class, added v-table pointer
11208 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011209 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011210 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011211 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011212 }
11213 else
11214 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011215 my $VSize_Old = getVTable_Size($CName, 1);
11216 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011217 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011218 if(isCopyingClass($Class_Id, 1))
11219 { # class has no constructors and v-table will be copied by applications, this may affect all methods
11220 my $ProblemType = "Added_Virtual_Method";
11221 if(isLeafClass($Class_Id, 1)) {
11222 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
11223 }
11224 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11225 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011226 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011227 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011228 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011229 else
11230 {
11231 my $ProblemType = "Added_Virtual_Method";
11232 if(isLeafClass($Class_Id, 1)) {
11233 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
11234 }
11235 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11236 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011237 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011238 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011239 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011240 }
11241 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011242 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11243 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011244 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011245 if(defined $VirtualTable{1}{$CName}
11246 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011247 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011248 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11249 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011250
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011251 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011252 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011253 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11254 foreach my $ASymbol (@Affected)
11255 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011256 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11257 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011258 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011259 next;
11260 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011261 }
11262 $CheckedSymbols{$Level}{$ASymbol} = 1;
11263 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11264 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011265 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011266 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011267 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011268 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011269 }
11270 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011271 else {
11272 # safe
11273 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011274 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011275 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11276 {
11277 next if($VirtualReplacement{$RemovedVFunc});
11278 if($RemovedVFunc eq $Interface
11279 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11280 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011281 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011282 next;
11283 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011284 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011285 { # became non-polymorphous class, removed v-table pointer
11286 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11287 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011288 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011289 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011290 }
11291 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11292 or $CompleteSignature{1}{$Interface}{"PureVirt"})
11293 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011294 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011295 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011296 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
11297 next;
11298 }
11299 my $VPos_New = -1;
11300 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011301 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011302 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
11303 }
11304 else
11305 {
11306 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011307 next;
11308 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011309 }
11310 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
11311 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11312 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
11313 {
11314 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11315 foreach my $ASymbol (@Affected)
11316 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011317 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11318 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011319 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011320 next;
11321 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011322 }
11323 my $ProblemType = "Removed_Virtual_Method";
11324 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
11325 $ProblemType = "Removed_Pure_Virtual_Method";
11326 }
11327 $CheckedSymbols{$Level}{$ASymbol} = 1;
11328 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
11329 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011330 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011331 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011332 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011333 }
11334 }
11335 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011336 }
11337 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011338 else
11339 { # Source-level
11340 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011341 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011342 next if($Interface eq $AddedVFunc);
11343 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011344 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011345 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11346 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011347 "Target"=>get_Signature($AddedVFunc, 2) );
11348 }
11349 }
11350 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11351 {
11352 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11353 {
11354 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11355 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011356 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011357 }
11358 }
11359 }
11360}
11361
11362sub find_MemberPair_Pos_byName($$)
11363{
11364 my ($Member_Name, $Pair_Type) = @_;
11365 $Member_Name=~s/\A[_]+|[_]+\Z//g;
11366 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11367 {
11368 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
11369 {
11370 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
11371 $Name=~s/\A[_]+|[_]+\Z//g;
11372 if($Name eq $Member_Name) {
11373 return $MemberPair_Pos;
11374 }
11375 }
11376 }
11377 return "lost";
11378}
11379
11380sub find_MemberPair_Pos_byVal($$)
11381{
11382 my ($Member_Value, $Pair_Type) = @_;
11383 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11384 {
11385 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
11386 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
11387 return $MemberPair_Pos;
11388 }
11389 }
11390 return "lost";
11391}
11392
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011393sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011394{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011395 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011396 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011397 if( $_->{"T1"} eq $_[0]
11398 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011399 {
11400 return 1;
11401 }
11402 }
11403 return 0;
11404}
11405
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011406sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011407{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011408 my %IDs = (
11409 "T1" => $_[0],
11410 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011411 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011412 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011413}
11414
11415sub isRenamed($$$$$)
11416{
11417 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
11418 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
11419 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011420 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011421 if(not defined $Type2->{"Memb"}{$MemPos}) {
11422 return "";
11423 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011424 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011425 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011426
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011427 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
11428 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011429 if($MemberPair_Pos_Rev eq "lost")
11430 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011431 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
11432 { # base type match
11433 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011434 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011435 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
11436 { # exact type match
11437 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011438 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011439 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
11440 { # size match
11441 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011442 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011443 if(isReserved($Pair_Name))
11444 { # reserved fields
11445 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011446 }
11447 }
11448 return "";
11449}
11450
11451sub isLastElem($$)
11452{
11453 my ($Pos, $TypeRef) = @_;
11454 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
11455 if($Name=~/last|count|max|total/i)
11456 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
11457 return 1;
11458 }
11459 elsif($Name=~/END|NLIMITS\Z/)
11460 { # __RLIMIT_NLIMITS
11461 return 1;
11462 }
11463 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
11464 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
11465 { # NImageFormats, NColorRoles
11466 return 1;
11467 }
11468 return 0;
11469}
11470
11471sub nonComparable($$)
11472{
11473 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011474
11475 my $N1 = $T1->{"Name"};
11476 my $N2 = $T2->{"Name"};
11477
11478 $N1=~s/\A(struct|union|enum) //;
11479 $N2=~s/\A(struct|union|enum) //;
11480
11481 if($N1 ne $N2
11482 and not isAnon($N1)
11483 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011484 { # different names
11485 if($T1->{"Type"} ne "Pointer"
11486 or $T2->{"Type"} ne "Pointer")
11487 { # compare base types
11488 return 1;
11489 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011490 if($N1!~/\Avoid\s*\*/
11491 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011492 {
11493 return 1;
11494 }
11495 }
11496 elsif($T1->{"Type"} ne $T2->{"Type"})
11497 { # different types
11498 if($T1->{"Type"} eq "Class"
11499 and $T2->{"Type"} eq "Struct")
11500 { # "class" to "struct"
11501 return 0;
11502 }
11503 elsif($T2->{"Type"} eq "Class"
11504 and $T1->{"Type"} eq "Struct")
11505 { # "struct" to "class"
11506 return 0;
11507 }
11508 else
11509 { # "class" to "enum"
11510 # "union" to "class"
11511 # ...
11512 return 1;
11513 }
11514 }
11515 return 0;
11516}
11517
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011518sub isOpaque($)
11519{
11520 my $T = $_[0];
11521 if(not defined $T->{"Memb"})
11522 {
11523 return 1;
11524 }
11525 return 0;
11526}
11527
11528sub removeVPtr($)
11529{ # support for old ABI dumps
11530 my $TPtr = $_[0];
11531 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
11532 if($#Pos>=1)
11533 {
11534 foreach my $Pos (0 .. $#Pos-1)
11535 {
11536 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
11537 }
11538 delete($TPtr->{"Memb"}{$#Pos});
11539 }
11540}
11541
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011542sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011543{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011544 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011545 return {} if(not $Type1_Id or not $Type2_Id);
11546
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011547 if($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011548 { # already merged
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011549 return $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011550 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011551
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011552 my %Type1 = get_Type($Type1_Id, 1);
11553 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011554 if(not $Type1{"Name"} or not $Type2{"Name"}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011555 return {};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011556 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011557
11558 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011559 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
11560 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011561
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011562 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
11563
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011564 my %SubProblems = ();
11565
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011566 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
11567 {
11568 if($Type1_Pure{"Type"}=~/Struct|Union/
11569 and $Type2_Pure{"Type"}=~/Struct|Union/)
11570 {
11571 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
11572 {
11573 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
11574 "Target"=>$Type1_Pure{"Name"},
11575 "Type_Name"=>$Type1_Pure{"Name"} );
11576
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011577 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011578 }
11579 }
11580 }
11581
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011582 if(not $Type1_Pure{"Size"}
11583 or not $Type2_Pure{"Size"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011584 { # including a case when "class Class { ... };" changed to "class Class;"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011585 if(not defined $Type1_Pure{"Memb"} or not defined $Type2_Pure{"Memb"}
11586 or index($Type1_Pure{"Name"}, "<")==-1 or index($Type2_Pure{"Name"}, "<")==-1)
11587 { # NOTE: template instances have no size
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011588 return {};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011589 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011590 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011591 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011592 { # skip recursive declarations
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011593 return {};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011594 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011595 return {} if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
11596 return {} if($SkipTypes{1}{$Type1_Pure{"Name"}});
11597 return {} if($SkipTypes{1}{$Type1{"Name"}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011598
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011599 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
11600 { # support for old ABI dumps
11601 # _vptr field added in 3.0
11602 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
11603 {
11604 if(defined $Type2_Pure{"Memb"}
11605 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
11606 {
11607 if(keys(%{$Type2_Pure{"Memb"}})==1) {
11608 delete($Type2_Pure{"Memb"}{0});
11609 }
11610 else {
11611 removeVPtr(\%Type2_Pure);
11612 }
11613 }
11614 }
11615 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
11616 {
11617 if(defined $Type1_Pure{"Memb"}
11618 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
11619 {
11620 if(keys(%{$Type1_Pure{"Memb"}})==1) {
11621 delete($Type1_Pure{"Memb"}{0});
11622 }
11623 else {
11624 removeVPtr(\%Type1_Pure);
11625 }
11626 }
11627 }
11628 }
11629
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011630 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
11631 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011632
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011633 if(not $UseOldDumps and %Typedef_1 and %Typedef_2
11634 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
11635 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011636 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011637 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
11638 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011639 if($Base_1{"Name"} ne $Base_2{"Name"})
11640 {
11641 if(differentDumps("G")
11642 or differentDumps("V"))
11643 { # different GCC versions or different dumps
11644 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
11645 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
11646 # std::__va_list and __va_list
11647 $Base_1{"Name"}=~s/\A(\w+::)+//;
11648 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011649 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
11650 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011651 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011652 }
11653 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
11654 and $Base_1{"Name"} ne $Base_2{"Name"})
11655 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011656 if($Level eq "Binary"
11657 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011658 {
11659 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
11660 "Target"=>$Typedef_1{"Name"},
11661 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011662 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
11663 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
11664 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011665 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
11666 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011667 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011668 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011669 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
11670 {
11671 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
11672 "Target"=>$Typedef_1{"Name"},
11673 "Type_Name"=>$Typedef_1{"Name"},
11674 "Old_Value"=>$Base_1{"Name"},
11675 "New_Value"=>$Base_2{"Name"} );
11676 }
11677 else
11678 {
11679 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
11680 "Target"=>$Typedef_1{"Name"},
11681 "Type_Name"=>$Typedef_1{"Name"},
11682 "Old_Value"=>$Base_1{"Name"},
11683 "New_Value"=>$Base_2{"Name"} );
11684 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011685 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011686 }
11687 }
11688 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
11689 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011690 my $TT1 = $Type1_Pure{"Type"};
11691 my $TT2 = $Type2_Pure{"Type"};
11692
11693 if($TT1 ne $TT2
11694 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011695 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011696 my $Short1 = $Type1_Pure{"Name"};
11697 my $Short2 = $Type2_Pure{"Name"};
11698
11699 $Short1=~s/\A\Q$TT1\E //ig;
11700 $Short2=~s/\A\Q$TT2\E //ig;
11701
11702 if($Short1 eq $Short2)
11703 {
11704 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
11705 "Target"=>$Type1_Pure{"Name"},
11706 "Type_Name"=>$Type1_Pure{"Name"},
11707 "Old_Value"=>lc($Type1_Pure{"Type"}),
11708 "New_Value"=>lc($Type2_Pure{"Type"}) );
11709 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011710 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011711 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011712 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011713 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011714 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
11715 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
11716 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11717 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011718 if($Level eq "Binary"
11719 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011720 {
11721 my $ProblemKind = "DataType_Size";
11722 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011723 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011724 {
11725 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
11726 $ProblemKind = "Size_Of_Copying_Class";
11727 }
11728 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
11729 {
11730 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
11731 $ProblemKind = "Size_Of_Allocable_Class_Increased";
11732 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011733 else
11734 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011735 # descreased size of allocable class
11736 # it has no special effects
11737 }
11738 }
11739 }
11740 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
11741 "Target"=>$Type1_Pure{"Name"},
11742 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011743 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011744 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011745 }
11746 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011747 if(defined $Type1_Pure{"BaseType"}
11748 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011749 { # checking base types
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011750 my $Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
11751 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011752 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011753 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}})) {
11754 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011755 }
11756 }
11757 }
11758 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
11759 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
11760 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
11761 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11762 { # detect removed and renamed fields
11763 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11764 next if(not $Member_Name);
11765 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);
11766 if($MemberPair_Pos eq "lost")
11767 {
11768 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11769 {
11770 if(isUnnamed($Member_Name))
11771 { # support for old-version dumps
11772 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011773 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011774 next;
11775 }
11776 }
11777 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11778 { # renamed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011779 $RenamedField{$Member_Pos} = $RenamedTo;
11780 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011781 }
11782 else
11783 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011784 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011785 }
11786 }
11787 elsif($Type1_Pure{"Type"} eq "Enum")
11788 {
11789 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11790 next if($Member_Value1 eq "");
11791 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11792 if($MemberPair_Pos ne "lost")
11793 { # renamed
11794 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11795 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11796 if($MemberPair_Pos_Rev eq "lost")
11797 {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011798 $RenamedField{$Member_Pos} = $RenamedTo;
11799 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011800 }
11801 else {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011802 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011803 }
11804 }
11805 else
11806 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011807 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011808 }
11809 }
11810 }
11811 else
11812 { # related
11813 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11814 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11815 }
11816 }
11817 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11818 { # detect added fields
11819 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11820 next if(not $Member_Name);
11821 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);
11822 if($MemberPair_Pos eq "lost")
11823 {
11824 if(isUnnamed($Member_Name))
11825 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011826 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011827 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011828 next;
11829 }
11830 }
11831 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11832 {
11833 if(not $RenamedField_Rev{$Member_Pos})
11834 { # added
11835 $AddedField{$Member_Pos}=1;
11836 }
11837 }
11838 }
11839 }
11840 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11841 { # detect moved fields
11842 my (%RelPos, %RelPosName, %AbsPos) = ();
11843 my $Pos = 0;
11844 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11845 { # relative positions in 1st version
11846 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11847 next if(not $Member_Name);
11848 if(not $RemovedField{$Member_Pos})
11849 { # old type without removed fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011850 $RelPos{1}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011851 $RelPosName{1}{$Pos} = $Member_Name;
11852 $AbsPos{1}{$Pos++} = $Member_Pos;
11853 }
11854 }
11855 $Pos = 0;
11856 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11857 { # relative positions in 2nd version
11858 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11859 next if(not $Member_Name);
11860 if(not $AddedField{$Member_Pos})
11861 { # new type without added fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011862 $RelPos{2}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011863 $RelPosName{2}{$Pos} = $Member_Name;
11864 $AbsPos{2}{$Pos++} = $Member_Pos;
11865 }
11866 }
11867 foreach my $Member_Name (keys(%{$RelPos{1}}))
11868 {
11869 my $RPos1 = $RelPos{1}{$Member_Name};
11870 my $AbsPos1 = $NameToPosA{$Member_Name};
11871 my $Member_Name2 = $Member_Name;
11872 if(my $RenamedTo = $RenamedField{$AbsPos1})
11873 { # renamed
11874 $Member_Name2 = $RenamedTo;
11875 }
11876 my $RPos2 = $RelPos{2}{$Member_Name2};
11877 if($RPos2 ne "" and $RPos1 ne $RPos2)
11878 { # different relative positions
11879 my $AbsPos2 = $NameToPosB{$Member_Name2};
11880 if($AbsPos1 ne $AbsPos2)
11881 { # different absolute positions
11882 my $ProblemType = "Moved_Field";
11883 if(not isPublic(\%Type1_Pure, $AbsPos1))
11884 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011885 if($Level eq "Source") {
11886 next;
11887 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011888 $ProblemType = "Moved_Private_Field";
11889 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011890 if($Level eq "Binary"
11891 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011892 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011893 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011894 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011895 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011896 if($MemSize1 ne $MemSize2) {
11897 $ProblemType .= "_And_Size";
11898 }
11899 }
11900 if($ProblemType eq "Moved_Private_Field") {
11901 next;
11902 }
11903 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11904 "Target"=>$Member_Name,
11905 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011906 "Old_Value"=>$RPos1,
11907 "New_Value"=>$RPos2 );
11908 }
11909 }
11910 }
11911 }
11912 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011913 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011914 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11915 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011916 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011917 if(my $RenamedTo = $RenamedField{$Member_Pos})
11918 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011919 if(defined $Constants{2}{$Member_Name})
11920 {
11921 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11922 { # define OLD NEW
11923 next; # Safe
11924 }
11925 }
11926
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011927 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11928 {
11929 if(isPublic(\%Type1_Pure, $Member_Pos))
11930 {
11931 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11932 "Target"=>$Member_Name,
11933 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011934 "Old_Value"=>$Member_Name,
11935 "New_Value"=>$RenamedTo );
11936 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011937 elsif(isReserved($Member_Name))
11938 {
11939 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11940 "Target"=>$Member_Name,
11941 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011942 "Old_Value"=>$Member_Name,
11943 "New_Value"=>$RenamedTo );
11944 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011945 }
11946 elsif($Type1_Pure{"Type"} eq "Enum")
11947 {
11948 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
11949 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
11950 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011951 "Old_Value"=>$Member_Name,
11952 "New_Value"=>$RenamedTo );
11953 }
11954 }
11955 elsif($RemovedField{$Member_Pos})
11956 { # removed
11957 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11958 {
11959 my $ProblemType = "Removed_Field";
11960 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011961 or isUnnamed($Member_Name))
11962 {
11963 if($Level eq "Source") {
11964 next;
11965 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011966 $ProblemType = "Removed_Private_Field";
11967 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011968 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011969 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011970 {
11971 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
11972 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011973 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 +040011974 { # changed offset
11975 $ProblemType .= "_And_Layout";
11976 }
11977 }
11978 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
11979 { # affected size
11980 $ProblemType .= "_And_Size";
11981 }
11982 }
11983 if($ProblemType eq "Removed_Private_Field") {
11984 next;
11985 }
11986 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11987 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011988 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011989 }
11990 elsif($Type2_Pure{"Type"} eq "Union")
11991 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011992 if($Level eq "Binary"
11993 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011994 {
11995 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
11996 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011997 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011998 }
11999 else
12000 {
12001 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
12002 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012003 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012004 }
12005 }
12006 elsif($Type1_Pure{"Type"} eq "Enum")
12007 {
12008 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
12009 "Target"=>$Member_Name,
12010 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012011 "Old_Value"=>$Member_Name );
12012 }
12013 }
12014 else
12015 { # changed
12016 my $MemberPair_Pos = $RelatedField{$Member_Pos};
12017 if($Type1_Pure{"Type"} eq "Enum")
12018 {
12019 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
12020 next if($Member_Value1 eq "");
12021 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
12022 next if($Member_Value2 eq "");
12023 if($Member_Value1 ne $Member_Value2)
12024 {
12025 my $ProblemType = "Enum_Member_Value";
12026 if(isLastElem($Member_Pos, \%Type1_Pure)) {
12027 $ProblemType = "Enum_Last_Member_Value";
12028 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012029 if($SkipConstants{1}{$Member_Name}) {
12030 $ProblemType = "Enum_Private_Member_Value";
12031 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012032 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12033 "Target"=>$Member_Name,
12034 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012035 "Old_Value"=>$Member_Value1,
12036 "New_Value"=>$Member_Value2 );
12037 }
12038 }
12039 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
12040 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012041 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
12042 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
12043
12044 if($Access1 ne "private"
12045 and $Access2 eq "private")
12046 {
12047 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
12048 "Target"=>$Member_Name,
12049 "Type_Name"=>$Type1_Pure{"Name"});
12050 }
12051 elsif($Access1 ne "protected"
12052 and $Access1 ne "private"
12053 and $Access2 eq "protected")
12054 {
12055 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
12056 "Target"=>$Member_Name,
12057 "Type_Name"=>$Type1_Pure{"Name"});
12058 }
12059
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012060 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
12061 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012062 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012063 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
12064 $SizeV1 = $BSize1;
12065 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012066 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012067 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
12068 $SizeV2 = $BSize2;
12069 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012070 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
12071 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012072 if($Level eq "Binary"
12073 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012074 {
12075 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
12076 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
12077 { # field size change (including anon-structures and unions)
12078 # - same types
12079 # - unnamed types
12080 # - bitfields
12081 my $ProblemType = "Field_Size";
12082 if(not isPublic(\%Type1_Pure, $Member_Pos)
12083 or isUnnamed($Member_Name))
12084 { # should not be accessed by applications, goes to "Low Severity"
12085 # example: "abidata" members in GStreamer types
12086 $ProblemType = "Private_".$ProblemType;
12087 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012088 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 +040012089 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012090 if($Type2_Pure{"Type"} ne "Union"
12091 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012092 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012093 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 +040012094 { # changed offset
12095 $ProblemType .= "_And_Layout";
12096 }
12097 }
12098 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12099 $ProblemType .= "_And_Type_Size";
12100 }
12101 }
12102 if($ProblemType eq "Private_Field_Size")
12103 { # private field size with no effect
12104 $ProblemType = "";
12105 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040012106 if($ProblemType eq "Field_Size")
12107 {
12108 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
12109 { # Low severity
12110 $ProblemType = "Struct_Field_Size_Increased";
12111 }
12112 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012113 if($ProblemType)
12114 { # register a problem
12115 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12116 "Target"=>$Member_Name,
12117 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012118 "Old_Size"=>$SizeV1,
12119 "New_Size"=>$SizeV2);
12120 }
12121 }
12122 }
12123 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
12124 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
12125 { # do NOT check bitfield type changes
12126 next;
12127 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012128 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012129 {
12130 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12131 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12132 {
12133 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
12134 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012135 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012136 }
12137 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12138 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12139 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012140 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012141 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012142 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012143 }
12144 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012145 my %Sub_SubChanges = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
12146 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012147 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012148 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12149 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012150
12151 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012152 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012153 or $ProblemType eq "Field_Type_And_Size"
12154 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012155 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012156 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012157 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012158 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012159 %{$Sub_SubChanges{"Field_Became_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012160 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012161 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012162 %{$Sub_SubChanges{"Field_Became_Non_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012163 }
12164 }
12165 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
12166 {
12167 if($RA==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012168 %{$Sub_SubChanges{"Field_Added_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012169 }
12170 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012171 %{$Sub_SubChanges{"Field_Became_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012172 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012173 }
12174 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
12175 {
12176 if($RR==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012177 %{$Sub_SubChanges{"Field_Removed_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012178 }
12179 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012180 %{$Sub_SubChanges{"Field_Became_Non_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012181 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012182 }
12183 }
12184 }
12185
12186 if($Level eq "Source")
12187 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012188 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012189 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012190 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12191 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012192
12193 if($ProblemType eq "Field_Type")
12194 {
12195 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012196 delete($Sub_SubChanges{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012197 }
12198 }
12199 }
12200 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012201
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012202 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012203 {
12204 my $ProblemType_Init = $ProblemType;
12205 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012206 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012207 if(not isPublic(\%Type1_Pure, $Member_Pos)
12208 or isUnnamed($Member_Name)) {
12209 $ProblemType = "Private_".$ProblemType;
12210 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012211 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 +040012212 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012213 if($Type2_Pure{"Type"} ne "Union"
12214 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012215 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012216 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 +040012217 { # changed offset
12218 $ProblemType .= "_And_Layout";
12219 }
12220 }
12221 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12222 $ProblemType .= "_And_Type_Size";
12223 }
12224 }
12225 }
12226 else
12227 {
12228 if(not isPublic(\%Type1_Pure, $Member_Pos)
12229 or isUnnamed($Member_Name)) {
12230 next;
12231 }
12232 }
12233 if($ProblemType eq "Private_Field_Type_And_Size")
12234 { # private field change with no effect
12235 next;
12236 }
12237 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12238 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012239 "Type_Name"=>$Type1_Pure{"Name"});
12240
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012241 foreach my $Attr (keys(%{$Sub_SubChanges{$ProblemType_Init}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012242 { # other properties
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012243 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubChanges{$ProblemType_Init}{$Attr};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012244 }
12245 }
12246 if(not isPublic(\%Type1_Pure, $Member_Pos))
12247 { # do NOT check internal type changes
12248 next;
12249 }
12250 if($MemberType1_Id and $MemberType2_Id)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012251 { # checking member type changes
12252 my $Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
12253
12254 my %DupProblems = ();
12255
12256 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012257 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012258 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012259 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012260 if(not defined $AllAffected)
12261 {
12262 if(defined $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}}) {
12263 next;
12264 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012265 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012266
12267 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
12268 $SubProblems{$Sub_SubProblemType}{$NewLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
12269
12270 if(not defined $AllAffected)
12271 {
12272 $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012273 }
12274 }
12275 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012276
12277 %DupProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012278 }
12279 }
12280 }
12281 }
12282 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
12283 { # checking added members, public and private
12284 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
12285 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040012286 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012287 if($AddedField{$Member_Pos})
12288 { # added
12289 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12290 {
12291 my $ProblemType = "Added_Field";
12292 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012293 or isUnnamed($Member_Name))
12294 {
12295 if($Level eq "Source") {
12296 next;
12297 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012298 $ProblemType = "Added_Private_Field";
12299 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012300 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012301 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012302 {
12303 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
12304 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012305 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 +040012306 { # changed offset
12307 $ProblemType .= "_And_Layout";
12308 }
12309 }
12310 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12311 $ProblemType .= "_And_Size";
12312 }
12313 }
12314 if($ProblemType eq "Added_Private_Field")
12315 { # skip added private fields
12316 next;
12317 }
12318 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12319 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012320 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012321 }
12322 elsif($Type2_Pure{"Type"} eq "Union")
12323 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012324 if($Level eq "Binary"
12325 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012326 {
12327 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
12328 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012329 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012330 }
12331 else
12332 {
12333 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
12334 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012335 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012336 }
12337 }
12338 elsif($Type2_Pure{"Type"} eq "Enum")
12339 {
12340 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
12341 next if($Member_Value eq "");
12342 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
12343 "Target"=>$Member_Name,
12344 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012345 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012346 }
12347 }
12348 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012349
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012350 pop(@RecurTypes);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012351 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012352}
12353
12354sub isUnnamed($) {
12355 return $_[0]=~/\Aunnamed\d+\Z/;
12356}
12357
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012358sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012359{
12360 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012361 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
12362 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
12363 $TypeName = uncover_typedefs($TypeName, $LibVersion);
12364 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012365 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012366 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012367 }
12368 return $TypeName;
12369}
12370
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012371sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012372{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012373 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012374 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012375 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
12376 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012377 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012378 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12379 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012380 return () if(not $Type{"Type"});
12381 if($Type{"Type"} ne $Type_Type)
12382 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012383 return () if(not $Type{"BaseType"});
12384 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012385 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012386 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012387 return %Type;
12388}
12389
12390my %TypeSpecAttributes = (
12391 "Const" => 1,
12392 "Volatile" => 1,
12393 "ConstVolatile" => 1,
12394 "Restrict" => 1,
12395 "Typedef" => 1
12396);
12397
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012398sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012399{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012400 my ($TypeId, $Info) = @_;
12401 if(not $TypeId or not $Info
12402 or not $Info->{$TypeId}) {
12403 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012404 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012405 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
12406 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
12407 }
12408 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012409 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012410 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012411 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012412 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012413 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012414 return %Type;
12415}
12416
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012417sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012418{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012419 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012420 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012421 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
12422 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012423 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012424 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
12425 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012426 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
12427 my $PLevel = 0;
12428 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
12429 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012430 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012431 return $PLevel if(not $Type{"BaseType"});
12432 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
12433 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
12434 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012435}
12436
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012437sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012438{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012439 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012440 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012441 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
12442 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012443 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012444 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12445 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012446 return %Type if(not $Type{"BaseType"});
12447 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012448 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012449 return %Type;
12450}
12451
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012452sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012453{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012454 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012455 return "" if(not $TypeId);
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 "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012459 my $Qual = "";
12460 if($Type{"Type"} eq "Pointer") {
12461 $Qual .= "*";
12462 }
12463 elsif($Type{"Type"} eq "Ref") {
12464 $Qual .= "&";
12465 }
12466 elsif($Type{"Type"} eq "ConstVolatile") {
12467 $Qual .= "const volatile";
12468 }
12469 elsif($Type{"Type"} eq "Const"
12470 or $Type{"Type"} eq "Volatile"
12471 or $Type{"Type"} eq "Restrict") {
12472 $Qual .= lc($Type{"Type"});
12473 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012474 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012475 return $BQual.$Qual;
12476}
12477
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012478sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012479{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012480 my ($TypeId, $Info) = @_;
12481 if(not $TypeId or not $Info
12482 or not $Info->{$TypeId}) {
12483 return ();
12484 }
12485 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012486 return %Type if(not $Type{"BaseType"});
12487 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012488 {
12489 if($Info->{$BTid}) {
12490 return %{$Info->{$BTid}};
12491 }
12492 else { # something is going wrong
12493 return ();
12494 }
12495 }
12496 else {
12497 return %Type;
12498 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012499}
12500
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012501sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012502{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012503 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012504 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012505 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12506 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012507}
12508
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012509sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012510{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012511 my $Symbol = $_[0];
12512 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
12513}
12514
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012515sub isInLineInst($$$) {
12516 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
12517}
12518
12519sub isTemplateInstance($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012520{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012521 my ($Symbol, $SInfo, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012522 if($CheckObjectsOnly)
12523 {
12524 if($Symbol!~/\A(_Z|\?)/) {
12525 return 0;
12526 }
12527 if(my $Signature = $tr_name{$Symbol})
12528 {
12529 if(index($Signature,">")==-1) {
12530 return 0;
12531 }
12532 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
12533 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012534 if(index($ShortName,"<")!=-1
12535 and index($ShortName,">")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012536 return 1;
12537 }
12538 }
12539 }
12540 }
12541 else
12542 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012543 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012544 {
12545 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
12546 {
12547 if(index($ClassName,"<")!=-1) {
12548 return 1;
12549 }
12550 }
12551 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012552 if(my $ShortName = $SInfo->{"ShortName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012553 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012554 if(index($ShortName,"<")!=-1
12555 and index($ShortName,">")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012556 return 1;
12557 }
12558 }
12559 }
12560 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012561}
12562
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012563sub isTemplateSpec($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012564{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012565 my ($Symbol, $SInfo, $LibVersion) = @_;
12566 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012567 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012568 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012569 { # class specialization
12570 return 1;
12571 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012572 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012573 { # method specialization
12574 return 1;
12575 }
12576 }
12577 return 0;
12578}
12579
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012580sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012581{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012582 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012583 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012584 { # non-public global data
12585 return 0;
12586 }
12587 if($CheckObjectsOnly) {
12588 return 0 if($Symbol=~/\A(_init|_fini)\Z/);
12589 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012590 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012591 { # support for old ABI dumps in --headers-only mode
12592 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
12593 {
12594 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
12595 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012596 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012597 if(not $PType or $PType eq "Unknown") {
12598 return 0;
12599 }
12600 }
12601 }
12602 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012603 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012604 {
12605 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012606 if($SkipSymbols{$LibVersion}{$Symbol})
12607 { # user defined symbols to ignore
12608 return 0;
12609 }
12610 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
12611 if(not $NameSpace and $ClassId)
12612 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012613 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012614 }
12615 if($NameSpace)
12616 { # user defined namespaces to ignore
12617 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
12618 return 0;
12619 }
12620 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
12621 { # nested namespaces
12622 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
12623 return 0;
12624 }
12625 }
12626 }
12627 if(my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
12628 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012629 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012630 { # --skip-headers or <skip_headers> (not <skip_including>)
12631 if($Skip==1) {
12632 return 0;
12633 }
12634 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012635 }
12636 if($SymbolsListPath and not $SymbolsList{$Symbol})
12637 { # user defined symbols
12638 return 0;
12639 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012640 if($SkipSymbolsListPath and $SkipSymbolsList{$Symbol})
12641 { # user defined symbols
12642 return 0;
12643 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012644 if($AppPath and not $SymbolsList_App{$Symbol})
12645 { # user defined symbols (in application)
12646 return 0;
12647 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012648 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
12649 { # non-target symbols
12650 return 0;
12651 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012652 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012653 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012654 if($CheckObjectsOnly)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012655 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012656 if(isTemplateInstance($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012657 return 0;
12658 }
12659 }
12660 else
12661 {
12662 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012663 or isInLineInst($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012664 {
12665 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
12666 { # inline virtual methods
12667 if($Type=~/InlineVirt/) {
12668 return 1;
12669 }
12670 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
12671 if(not $Allocable)
12672 { # check bases
12673 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
12674 {
12675 if(not isCopyingClass($DCId, $LibVersion))
12676 { # exists a derived class without default c-tor
12677 $Allocable=1;
12678 last;
12679 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012680 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012681 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012682 if(not $Allocable) {
12683 return 0;
12684 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012685 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012686 else
12687 { # inline non-virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012688 return 0;
12689 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012690 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012691 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012692 }
12693 }
12694 return 1;
12695}
12696
12697sub mergeImpl()
12698{
12699 my $DiffCmd = get_CmdPath("diff");
12700 if(not $DiffCmd) {
12701 exitStatus("Not_Found", "can't find \"diff\"");
12702 }
12703 foreach my $Interface (sort keys(%{$Symbol_Library{1}}))
12704 { # implementation changes
12705 next if($CompleteSignature{1}{$Interface}{"Private"});
12706 next if(not $CompleteSignature{1}{$Interface}{"Header"} and not $CheckObjectsOnly);
12707 next if(not $Symbol_Library{2}{$Interface} and not $Symbol_Library{2}{$SymVer{2}{$Interface}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012708 if(not symbolFilter($Interface, 1, "Affected", "Binary")) {
12709 next;
12710 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012711 my $Impl1 = canonifyImpl($Interface_Impl{1}{$Interface});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012712 next if(not $Impl1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012713 my $Impl2 = canonifyImpl($Interface_Impl{2}{$Interface});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012714 next if(not $Impl2);
12715 if($Impl1 ne $Impl2)
12716 {
12717 writeFile("$TMP_DIR/impl1", $Impl1);
12718 writeFile("$TMP_DIR/impl2", $Impl2);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040012719 my $Diff = `$DiffCmd -rNau \"$TMP_DIR/impl1\" \"$TMP_DIR/impl2\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012720 $Diff=~s/(---|\+\+\+).+\n//g;
12721 $Diff=~s/[ ]{3,}/ /g;
12722 $Diff=~s/\n\@\@/\n \n\@\@/g;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040012723 unlink("$TMP_DIR/impl1");
12724 unlink("$TMP_DIR/impl2");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040012725 %{$CompatProblems_Impl{$Interface}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012726 "Diff" => get_CodeView($Diff) );
12727 }
12728 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012729
12730 # clean memory
12731 %Interface_Impl = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012732}
12733
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012734sub canonifyImpl($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012735{
12736 my $FuncBody= $_[0];
12737 return "" if(not $FuncBody);
12738 $FuncBody=~s/0x[a-f\d]+/0x?/g;# addr
12739 $FuncBody=~s/((\A|\n)[a-z]+[\t ]+)[a-f\d]+([^x]|\Z)/$1?$3/g;# call, jump
12740 $FuncBody=~s/# [a-f\d]+ /# ? /g;# call, jump
12741 $FuncBody=~s/%([a-z]+[a-f\d]*)/\%reg/g;# registers
12742 while($FuncBody=~s/\nnop[ \t]*(\n|\Z)/$1/g){};# empty op
12743 $FuncBody=~s/<.+?\.cpp.+?>/<name.cpp>/g;
12744 $FuncBody=~s/(\A|\n)[a-f\d]+ </$1? </g;# 5e74 <_ZN...
12745 $FuncBody=~s/\.L\d+/.L/g;
12746 $FuncBody=~s/#(-?)\d+/#$1?/g;# r3, [r3, #120]
12747 $FuncBody=~s/[\n]{2,}/\n/g;
12748 return $FuncBody;
12749}
12750
12751sub get_CodeView($)
12752{
12753 my $Code = $_[0];
12754 my $View = "";
12755 foreach my $Line (split(/\n/, $Code))
12756 {
12757 if($Line=~s/\A(\+|-)/$1 /g)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012758 { # bold line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012759 $View .= "<tr><td><b>".htmlSpecChars($Line)."</b></td></tr>\n";
12760 }
12761 else {
12762 $View .= "<tr><td>".htmlSpecChars($Line)."</td></tr>\n";
12763 }
12764 }
12765 return "<table class='code_view'>$View</table>\n";
12766}
12767
12768sub getImplementations($$)
12769{
12770 my ($LibVersion, $Path) = @_;
12771 return if(not $LibVersion or not -e $Path);
12772 if($OSgroup eq "macos")
12773 {
12774 my $OtoolCmd = get_CmdPath("otool");
12775 if(not $OtoolCmd) {
12776 exitStatus("Not_Found", "can't find \"otool\"");
12777 }
12778 my $CurInterface = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040012779 foreach my $Line (split(/\n/, `$OtoolCmd -tv \"$Path\" 2>\"$TMP_DIR/null\"`))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012780 {
12781 if($Line=~/\A\s*_(\w+)\s*:/i) {
12782 $CurInterface = $1;
12783 }
12784 elsif($Line=~/\A\s*[\da-z]+\s+(.+?)\Z/i) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012785 $Interface_Impl{$LibVersion}{$CurInterface} .= $1."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012786 }
12787 }
12788 }
12789 else
12790 {
12791 my $ObjdumpCmd = get_CmdPath("objdump");
12792 if(not $ObjdumpCmd) {
12793 exitStatus("Not_Found", "can't find \"objdump\"");
12794 }
12795 my $CurInterface = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040012796 foreach my $Line (split(/\n/, `$ObjdumpCmd -d \"$Path\" 2>\"$TMP_DIR/null\"`))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012797 {
12798 if($Line=~/\A[\da-z]+\s+<(\w+)>/i) {
12799 $CurInterface = $1;
12800 }
12801 else
12802 { # x86: 51fa:(\t)89 e5 (\t)mov %esp,%ebp
12803 # arm: 5020:(\t)e24cb004(\t)sub(\t)fp, ip, #4(\t); 0x4
12804 if($Line=~/\A\s*[a-f\d]+:\s+([a-f\d]+\s+)+([a-z]+\s+.*?)\s*(;.*|)\Z/i) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012805 $Interface_Impl{$LibVersion}{$CurInterface} .= $2."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012806 }
12807 }
12808 }
12809 }
12810}
12811
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012812sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012813{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012814 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012815 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12816 {
12817 if(link_symbol($Symbol, 1, "+Deps"))
12818 { # linker can find a new symbol
12819 # in the old-version library
12820 # So, it's not a new symbol
12821 next;
12822 }
12823 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012824 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012825 next;
12826 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012827 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012828 }
12829}
12830
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012831sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012832{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012833 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012834 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12835 {
12836 if($CheckObjectsOnly) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012837 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012838 }
12839 if(link_symbol($Symbol, 2, "+Deps"))
12840 { # linker can find an old symbol
12841 # in the new-version library
12842 next;
12843 }
12844 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012845 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012846 next;
12847 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012848 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012849 }
12850}
12851
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012852sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012853{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012854 my $Level = $_[0];
12855 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012856 { # checking added symbols
12857 next if($CompleteSignature{2}{$Symbol}{"Private"});
12858 next if(not $CompleteSignature{2}{$Symbol}{"Header"} and not $CheckObjectsOnly);
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012859 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012860 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012861 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012862 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012863 { # checking removed symbols
12864 next if($CompleteSignature{1}{$Symbol}{"Private"});
12865 next if(not $CompleteSignature{1}{$Symbol}{"Header"} and not $CheckObjectsOnly);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012866 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012867 { # skip v-tables for templates, that should not be imported by applications
12868 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012869 if(my $CName = $VTableClass{$Symbol})
12870 {
12871 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12872 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012873 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012874 next;
12875 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012876 }
12877 }
12878 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012879 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012880 }
12881 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12882 { # symbols for pure virtual methods cannot be called by clients
12883 next;
12884 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012885 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012886 }
12887}
12888
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012889sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012890{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012891 my ($LibVersion, $V) = @_;
12892 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12893 return $Cache{"checkDump"}{$LibVersion}{$V};
12894 }
12895 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012896}
12897
12898sub detectAdded_H($)
12899{
12900 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012901 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12902 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012903 if($Level eq "Source")
12904 { # remove symbol version
12905 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12906 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012907
12908 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12909 { # skip artificial constructors
12910 next;
12911 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012912 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012913 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12914 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012915 next;
12916 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012917 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012918 next;
12919 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012920 if(not defined $CompleteSignature{1}{$Symbol}
12921 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12922 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012923 if($UsedDump{2}{"SrcBin"})
12924 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012925 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012926 { # support for old and different (!) ABI dumps
12927 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12928 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012929 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012930 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012931 {
12932 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12933 {
12934 if($Lang eq "C")
12935 { # support for old ABI dumps: missed extern "C" functions
12936 next;
12937 }
12938 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012939 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012940 else
12941 {
12942 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012943 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012944 next;
12945 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012946 }
12947 }
12948 }
12949 }
12950 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012951 }
12952 }
12953}
12954
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012955sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012956{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012957 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012958 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12959 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012960 if($Level eq "Source")
12961 { # remove symbol version
12962 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12963 $Symbol=$SN;
12964 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012965 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12966 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012967 next;
12968 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012969 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012970 next;
12971 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012972 if(not defined $CompleteSignature{2}{$Symbol}
12973 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012974 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012975 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012976 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012977 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012978 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012979 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
12980 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012981 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012982 if($CheckHeadersOnly)
12983 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012984 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
12985 {
12986 if($Lang eq "C")
12987 { # support for old ABI dumps: missed extern "C" functions
12988 next;
12989 }
12990 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012991 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012992 else
12993 {
12994 if(not link_symbol($Symbol, 1, "-Deps"))
12995 { # skip removed inline symbols
12996 next;
12997 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012998 }
12999 }
13000 }
13001 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040013002 if(not checkDump(1, "2.15"))
13003 {
13004 if($Symbol=~/_IT_E\Z/)
13005 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
13006 next;
13007 }
13008 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013009 if(not $CompleteSignature{1}{$Symbol}{"Class"})
13010 {
13011 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
13012 {
13013 if(defined $Constants{2}{$Short})
13014 {
13015 my $Val = $Constants{2}{$Short}{"Value"};
13016 if(defined $Func_ShortName{2}{$Val})
13017 { # old name defined to new
13018 next;
13019 }
13020 }
13021 }
13022
13023 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013024 $RemovedInt{$Level}{$Symbol} = 1;
13025 if($Level eq "Source")
13026 { # search for a source-compatible equivalent
13027 setAlternative($Symbol, $Level);
13028 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013029 }
13030 }
13031}
13032
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013033sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013034{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013035 my $Level = $_[0];
13036 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013037 { # checking added symbols
13038 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013039 next if($CompleteSignature{2}{$Symbol}{"Private"});
13040 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013041 if($Level eq "Binary")
13042 {
13043 if($CompleteSignature{2}{$Symbol}{"InLine"})
13044 {
13045 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
13046 { # skip inline non-virtual functions
13047 next;
13048 }
13049 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013050 }
13051 else
13052 { # Source
13053 if($SourceAlternative_B{$Symbol}) {
13054 next;
13055 }
13056 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013057 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013058 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013059 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013060 { # checking removed symbols
13061 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013062 next if($CompleteSignature{1}{$Symbol}{"Private"});
13063 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013064 if($Level eq "Binary")
13065 {
13066 if($CompleteSignature{1}{$Symbol}{"InLine"})
13067 {
13068 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
13069 { # skip inline non-virtual functions
13070 next;
13071 }
13072 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013073 }
13074 else
13075 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013076 if(my $Alt = $SourceAlternative{$Symbol})
13077 {
13078 if(defined $CompleteSignature{1}{$Alt}
13079 and $CompleteSignature{1}{$Symbol}{"Const"})
13080 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013081 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013082 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{"this"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013083 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013084 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013085 }
13086 else
13087 { # do NOT show removed symbol
13088 next;
13089 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013090 }
13091 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013092 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013093 }
13094}
13095
13096sub addParamNames($)
13097{
13098 my $LibraryVersion = $_[0];
13099 return if(not keys(%AddIntParams));
13100 my $SecondVersion = $LibraryVersion==1?2:1;
13101 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
13102 {
13103 next if(not keys(%{$AddIntParams{$Interface}}));
13104 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013105 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013106 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
13107 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013108 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013109 if(defined $CompleteSignature{$SecondVersion}{$Interface}
13110 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
13111 {
13112 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
13113 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13114 }
13115 }
13116 else {
13117 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13118 }
13119 }
13120 }
13121 }
13122}
13123
13124sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013125{ # detect changed typedefs to show
13126 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013127 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
13128 {
13129 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013130 my $BName1 = $Typedef_BaseName{1}{$Typedef};
13131 if(not $BName1 or isAnon($BName1)) {
13132 next;
13133 }
13134 my $BName2 = $Typedef_BaseName{2}{$Typedef};
13135 if(not $BName2 or isAnon($BName2)) {
13136 next;
13137 }
13138 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013139 $ChangedTypedef{$Typedef} = 1;
13140 }
13141 }
13142}
13143
13144sub get_symbol_suffix($$)
13145{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013146 my ($Symbol, $Full) = @_;
13147 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040013148 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013149 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013150 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013151 if(not $Full) {
13152 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
13153 }
13154 return $Suffix;
13155}
13156
13157sub get_symbol_prefix($$)
13158{
13159 my ($Symbol, $LibVersion) = @_;
13160 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
13161 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13162 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013163 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013164 }
13165 return $ShortName;
13166}
13167
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013168sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013169{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013170 my $Symbol = $_[0];
13171 my $PSymbol = $Symbol;
13172 if(not defined $CompleteSignature{2}{$PSymbol}
13173 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
13174 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
13175 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013176 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013177 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013178 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013179 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013180 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
13181 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013182 {
13183 if(defined $CompleteSignature{2}{$PSymbol}
13184 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13185 {
13186 $SourceAlternative{$Symbol} = $PSymbol;
13187 $SourceAlternative_B{$PSymbol} = $Symbol;
13188 if(not defined $CompleteSignature{1}{$PSymbol}
13189 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13190 $SourceReplacement{$Symbol} = $PSymbol;
13191 }
13192 }
13193 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013194 }
13195 else
13196 {
13197 foreach my $Sp ("KV", "VK", "K", "V")
13198 {
13199 if($PSymbol=~s/\A_ZN$Sp/_ZN/
13200 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
13201 {
13202 if(defined $CompleteSignature{2}{$PSymbol}
13203 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13204 {
13205 $SourceAlternative{$Symbol} = $PSymbol;
13206 $SourceAlternative_B{$PSymbol} = $Symbol;
13207 if(not defined $CompleteSignature{1}{$PSymbol}
13208 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13209 $SourceReplacement{$Symbol} = $PSymbol;
13210 }
13211 }
13212 }
13213 $PSymbol = $Symbol;
13214 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013215 }
13216 }
13217 }
13218 return "";
13219}
13220
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013221sub getSymKind($$)
13222{
13223 my ($Symbol, $LibVersion) = @_;
13224 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
13225 {
13226 return "Global_Data";
13227 }
13228 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13229 {
13230 return "Method";
13231 }
13232 return "Function";
13233}
13234
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013235sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013236{
13237 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013238 my %SubProblems = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013239
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013240 mergeBases($Level);
13241
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013242 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013243 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013244 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013245 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013246 next;
13247 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013248 if(defined $CompleteSignature{1}{$Symbol}
13249 and $CompleteSignature{1}{$Symbol}{"Header"})
13250 { # double-check added symbol
13251 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013252 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013253 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013254 next;
13255 }
13256 if($Symbol=~/\A(_Z|\?)/)
13257 { # C++
13258 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
13259 }
13260 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
13261 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013262 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
13263 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013264 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013265 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013266 {
13267 if($TName_Tid{1}{$AffectedClass_Name})
13268 { # class should exist in previous version
13269 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
13270 { # old v-table is NOT copied by old applications
13271 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
13272 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013273 "Target"=>get_Signature($Symbol, 2),
13274 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013275 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013276 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013277 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013278 }
13279 }
13280 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013281 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
13282 { # check all removed exported symbols
13283 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013284 next;
13285 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013286 if(defined $CompleteSignature{2}{$Symbol}
13287 and $CompleteSignature{2}{$Symbol}{"Header"})
13288 { # double-check removed symbol
13289 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013290 }
13291 if($CompleteSignature{1}{$Symbol}{"Private"})
13292 { # skip private methods
13293 next;
13294 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013295 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013296 next;
13297 }
13298 $CheckedSymbols{$Level}{$Symbol} = 1;
13299 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
13300 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013301 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
13302 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013303 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013304 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
13305 {
13306 if($TName_Tid{2}{$AffectedClass_Name})
13307 { # class should exist in newer version
13308 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
13309 { # old v-table is NOT copied by old applications
13310 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
13311 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013312 "Target"=>get_Signature($OverriddenMethod, 1),
13313 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013314 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013315 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013316 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013317 }
13318 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013319 if($Level eq "Binary"
13320 and $OSgroup eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013321 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013322 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013323 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013324 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013325 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013326 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013327 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013328 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013329 {
13330 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
13331 "Target"=>$tr_name{$Symbol},
13332 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013333 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013334 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013335 else
13336 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013337 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013338 "Target"=>$tr_name{$Symbol},
13339 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013340 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013341 }
13342 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013343 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013344 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013345 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013346 {
13347 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
13348 "Target"=>$tr_name{$Symbol},
13349 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013350 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013351 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013352 else
13353 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013354 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013355 "Target"=>$tr_name{$Symbol},
13356 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013357 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013358 }
13359 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013360 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
13361 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
13362 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
13363 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
13364 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013365 {
13366 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013367 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013368 $ProblemType = "Global_Data_Symbol_Changed_Type";
13369 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013370 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
13371 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013372 "Old_Type"=>$RTName1,
13373 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013374 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013375 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013376 }
13377 }
13378 }
13379 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013380 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013381 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013382 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013383 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013384 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013385 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013386 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013387 if($CompleteSignature{1}{$Symbol}{"Constructor"})
13388 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013389 if($Symbol=~/(C[1-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013390 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013391 my $CtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013392 $NewSym=~s/(C[1-2][EI])/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013393 }
13394 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013395 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
13396 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013397 if($Symbol=~/(D[0-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013398 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013399 my $DtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013400 $NewSym=~s/(D[0-2][EI])/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013401 }
13402 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013403 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013404 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013405 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013406 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013407 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013408 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013409 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013410 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013411 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013412 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013413 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013414 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013415 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013416 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013417 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013418 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013419 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013420 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013421 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013422 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013423 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013424 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013425 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013426 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013427 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013428 { # "volatile" to non-"volatile"
13429
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013430 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013431 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013432 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013433 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013434 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013435 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013436 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013437 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013438 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013439 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013440 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013441 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013442 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013443 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013444 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013445 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013446 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013447 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
13448 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013449 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013450 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013451 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013452 }
13453 }
13454 }
13455 }
13456 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013457 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
13458 { # checking symbols
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013459 $CurrentSymbol = $Symbol;
13460
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013461 my ($SN, $SS, $SV) = separate_symbol($Symbol);
13462 if($Level eq "Source")
13463 { # remove symbol version
13464 $Symbol=$SN;
13465 }
13466 else
13467 { # Binary
13468 if(not $SV)
13469 { # symbol without version
13470 if(my $VSym = $SymVer{1}{$Symbol})
13471 { # the symbol is linked with versioned symbol
13472 if($CompleteSignature{2}{$VSym}{"MnglName"})
13473 { # show report for symbol@ver only
13474 next;
13475 }
13476 elsif(not link_symbol($VSym, 2, "-Deps"))
13477 { # changed version: sym@v1 to sym@v2
13478 # do NOT show report for symbol
13479 next;
13480 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013481 }
13482 }
13483 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013484 my $PSymbol = $Symbol;
13485 if($Level eq "Source"
13486 and my $S = $SourceReplacement{$Symbol})
13487 { # take a source-compatible replacement function
13488 $PSymbol = $S;
13489 }
13490 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013491 { # private symbols
13492 next;
13493 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013494 if(not defined $CompleteSignature{1}{$Symbol}
13495 or not defined $CompleteSignature{2}{$PSymbol})
13496 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013497 next;
13498 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013499 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
13500 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
13501 { # no mangled name
13502 next;
13503 }
13504 if(not $CompleteSignature{1}{$Symbol}{"Header"}
13505 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013506 { # without a header
13507 next;
13508 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013509
13510 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
13511 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13512 { # became pure
13513 next;
13514 }
13515 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13516 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13517 { # became non-pure
13518 next;
13519 }
13520
13521 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
13522 { # exported, target, inline virtual and pure virtual
13523 next;
13524 }
13525 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
13526 { # exported, target, inline virtual and pure virtual
13527 next;
13528 }
13529
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013530 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013531 {
13532 if($CompleteSignature{1}{$Symbol}{"Data"}
13533 and $CompleteSignature{2}{$PSymbol}{"Data"})
13534 {
13535 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
13536 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
13537 if(defined $Value1)
13538 {
13539 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
13540 if(defined $Value2)
13541 {
13542 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
13543 if($Value1 ne $Value2)
13544 {
13545 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
13546 "Old_Value"=>$Value1,
13547 "New_Value"=>$Value2,
13548 "Target"=>get_Signature($Symbol, 1) );
13549 }
13550 }
13551 }
13552 }
13553 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013554
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013555 if($CompleteSignature{2}{$PSymbol}{"Private"})
13556 {
13557 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
13558 "Target"=>get_Signature_M($PSymbol, 2) );
13559 }
13560 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
13561 and $CompleteSignature{2}{$PSymbol}{"Protected"})
13562 {
13563 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
13564 "Target"=>get_Signature_M($PSymbol, 2) );
13565 }
13566 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
13567 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
13568 {
13569 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
13570 "Target"=>get_Signature_M($PSymbol, 2) );
13571 }
13572
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013573 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013574 mergeVirtualTables($Symbol, $Level);
13575
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013576 if($COMPILE_ERRORS)
13577 { # if some errors occurred at the compiling stage
13578 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013579 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013580 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013581 { # missed information about parameters in newer version
13582 next;
13583 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013584 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013585 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013586 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013587 next;
13588 }
13589 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013590 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013591 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013592 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013593 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13594 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013595 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
13596 "Target"=>get_Signature($Symbol, 1)
13597 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013598 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013599 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013600 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13601 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013602 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013603 "Target"=>get_Signature($Symbol, 1)
13604 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013605 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013606 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
13607 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013608 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013609 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013610 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013611 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
13612 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
13613 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013614 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013615 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013616 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
13617 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013618 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013619 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013620 my $ProblemType = "Virtual_Method_Position";
13621 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
13622 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013623 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013624 if(isUsedClass($Class_Id, 1, $Level))
13625 {
13626 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013627 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013628 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013629 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
13630 next;
13631 }
13632 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013633 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013634 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
13635 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013636 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013637 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013638 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013639 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013640 }
13641 }
13642 }
13643 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013644 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13645 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013646 { # do NOT check type changes in pure virtuals
13647 next;
13648 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013649 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013650 if($Symbol=~/\A(_Z|\?)/
13651 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013652 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013653 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013654 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013655 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013656 }
13657 }
13658 else
13659 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013660 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013661 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013662 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013663 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
13664 last if($PType2_Name eq "...");
13665 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
13666 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013667 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013668 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013669 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013670 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
13671 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013672 if($#Positions1==-1 or $#Positions2>$#Positions1) {
13673 $ParamPos_Prev = "lost";
13674 }
13675 }
13676 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013677 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013678 }
13679 if($ParamPos_Prev eq "lost")
13680 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013681 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013682 {
13683 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013684 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013685 $ProblemType = "Added_Unnamed_Parameter";
13686 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013687 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013688 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013689 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013690 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013691 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013692 }
13693 else
13694 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013695 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013696 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013697 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013698 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
13699 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013700 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013701 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013702 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013703 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013704 "Target"=>$PName_Old,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013705 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013706 "Param_Type"=>$PType2_Name,
13707 "Old_Value"=>$PName_Old,
13708 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013709 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013710 }
13711 }
13712 else
13713 {
13714 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013715 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013716 $ProblemType = "Added_Middle_Unnamed_Parameter";
13717 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013718 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013719 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013720 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013721 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013722 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013723 }
13724 }
13725 }
13726 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013727 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013728 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013729 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013730 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013731 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013732 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013733 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013734 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013735 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013736 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
13737 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013738 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013739 }
13740 }
13741 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013742 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013743 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013744 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013745 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
13746 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013747 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
13748 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013749 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013750 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013751 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013752 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
13753 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013754 if($#Positions2==-1 or $#Positions2<$#Positions1) {
13755 $ParamPos_New = "lost";
13756 }
13757 }
13758 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013759 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013760 }
13761 if($ParamPos_New eq "lost")
13762 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013763 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013764 {
13765 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013766 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013767 $ProblemType = "Removed_Unnamed_Parameter";
13768 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013769 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013770 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013771 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013772 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013773 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013774 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013775 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013776 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013777 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013778 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013779 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013780 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013781 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013782 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013783 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013784 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013785 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013786 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013787 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013788 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013789 "Old_Value"=>$PName,
13790 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013791 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013792 }
13793 }
13794 else
13795 {
13796 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013797 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013798 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13799 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013800 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013801 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013802 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013803 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013804 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013805 }
13806 }
13807 }
13808 }
13809 }
13810 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013811 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13812 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013813 my %RC_SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013814
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013815 foreach my $SubProblemType (keys(%RC_SubProblems))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013816 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013817 my $New_Value = $RC_SubProblems{$SubProblemType}{"New_Value"};
13818 my $Old_Value = $RC_SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013819 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013820
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013821 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013822 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013823 if($SubProblemType eq "Return_Type_And_Size") {
13824 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13825 }
13826 elsif($SubProblemType eq "Return_Type_Format") {
13827 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13828 }
13829 else {
13830 $ProblemTypes{"Global_Data_Type"} = 1;
13831 }
13832
13833 # quals
13834 if($SubProblemType eq "Return_Type"
13835 or $SubProblemType eq "Return_Type_And_Size"
13836 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013837 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013838 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13839 { # const to non-const
13840 if($RR==2) {
13841 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13842 }
13843 else {
13844 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13845 }
13846 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013847 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013848 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13849 { # non-const to const
13850 if($RA==2) {
13851 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13852 }
13853 else {
13854 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13855 }
13856 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013857 }
13858 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013859 }
13860 else
13861 {
13862 # quals
13863 if($SubProblemType eq "Return_Type"
13864 or $SubProblemType eq "Return_Type_And_Size"
13865 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013866 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013867 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013868 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013869 if(addedQual($Old_Value, $New_Value, "volatile"))
13870 {
13871 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13872 if($Level ne "Source"
13873 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13874 $ProblemTypes{"Return_Type"} = 1;
13875 }
13876 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013877 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013878 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13879 {
13880 if($RA==2) {
13881 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13882 }
13883 else {
13884 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13885 }
13886 if($Level ne "Source"
13887 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13888 $ProblemTypes{"Return_Type"} = 1;
13889 }
13890 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013891 }
13892 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013893 if($Level eq "Binary"
13894 and not $CompleteSignature{1}{$Symbol}{"Data"})
13895 {
13896 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13897 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13898 { # if one of the architectures is unknown
13899 # then set other arhitecture to unknown too
13900 ($Arch1, $Arch2) = ("unknown", "unknown");
13901 }
13902 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013903 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013904 {
13905 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13906 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13907 }
13908 else
13909 {
13910 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13911 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13912 }
13913
13914 if($SubProblemType eq "Return_Type_Became_Void")
13915 {
13916 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13917 { # parameters stack has been affected
13918 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013919 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013920 }
13921 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013922 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013923 }
13924 }
13925 }
13926 elsif($SubProblemType eq "Return_Type_From_Void")
13927 {
13928 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13929 { # parameters stack has been affected
13930 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013931 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013932 }
13933 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013934 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013935 }
13936 }
13937 }
13938 elsif($SubProblemType eq "Return_Type"
13939 or $SubProblemType eq "Return_Type_And_Size"
13940 or $SubProblemType eq "Return_Type_Format")
13941 {
13942 if($Conv1{"Method"} ne $Conv2{"Method"})
13943 {
13944 if($Conv1{"Method"} eq "stack")
13945 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013946 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013947 }
13948 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013949 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013950 }
13951 }
13952 else
13953 {
13954 if($Conv1{"Method"} eq "reg")
13955 {
13956 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13957 {
13958 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013959 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013960 }
13961 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013962 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013963 }
13964 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013965 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013966 }
13967 }
13968 }
13969 }
13970 }
13971 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013972
13973 if(not keys(%ProblemTypes))
13974 { # default
13975 $ProblemTypes{$SubProblemType} = 1;
13976 }
13977
13978 foreach my $ProblemType (keys(%ProblemTypes))
13979 { # additional
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013980 $CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"} = $RC_SubProblems{$SubProblemType};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013981 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013982 }
13983 if($ReturnType1_Id and $ReturnType2_Id)
13984 {
13985 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013986 my $Sub_SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
13987
13988 my $AddProblems = {};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013989
13990 if($CompleteSignature{1}{$Symbol}{"Data"})
13991 {
13992 if($Level eq "Binary")
13993 {
13994 if(get_PLevel($ReturnType1_Id, 1)==0)
13995 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013996 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013997 { # add "Global_Data_Size" problem
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013998 my $New_Value = $Sub_SubProblems->{$SubProblemType}{"New_Value"};
13999 my $Old_Value = $Sub_SubProblems->{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014000 if($SubProblemType eq "DataType_Size")
14001 { # add a new problem
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014002 $AddProblems->{"Global_Data_Size"} = $Sub_SubProblems->{$SubProblemType};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014003 }
14004 }
14005 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014006 if(not defined $AddProblems->{"Global_Data_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014007 {
14008 if(defined $GlobalDataObject{1}{$Symbol}
14009 and defined $GlobalDataObject{2}{$Symbol})
14010 {
14011 my $Old_Size = $GlobalDataObject{1}{$Symbol};
14012 my $New_Size = $GlobalDataObject{2}{$Symbol};
14013 if($Old_Size!=$New_Size)
14014 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014015 $AddProblems->{"Global_Data_Size"}{"retval"} = {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014016 "Old_Size"=>$Old_Size*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014017 "New_Size"=>$New_Size*$BYTE_SIZE };
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014018 }
14019 }
14020 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014021 }
14022 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014023
14024 foreach my $SubProblemType (keys(%{$AddProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014025 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014026 foreach my $SubLocation (keys(%{$AddProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014027 {
14028 my $NewLocation = ($SubLocation)?"retval->".$SubLocation:"retval";
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014029 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $AddProblems->{$SubProblemType}{$SubLocation};
14030 }
14031 }
14032
14033 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
14034 {
14035 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
14036 {
14037 my $NewLocation = ($SubLocation)?"retval->".$SubLocation:"retval";
14038 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014039 }
14040 }
14041 }
14042
14043 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014044 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
14045 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
14046 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014047 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014048 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014049 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
14050 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014051 if($ThisPtr1_Id and $ThisPtr2_Id)
14052 {
14053 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014054 my $Sub_SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
14055 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014056 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014057 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014058 {
14059 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014060 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014061 }
14062 }
14063 }
14064 }
14065 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014066 if($Level eq "Binary") {
14067 mergeVTables($Level);
14068 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014069 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
14070 $CheckedSymbols{$Level}{$Symbol} = 1;
14071 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014072}
14073
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014074sub rmQuals($$)
14075{
14076 my ($Value, $Qual) = @_;
14077 if(not $Qual) {
14078 return $Value;
14079 }
14080 if($Qual eq "all")
14081 { # all quals
14082 $Qual = "const|volatile|restrict";
14083 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014084 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014085 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014086 }
14087 return $Value;
14088}
14089
14090sub cmpBTypes($$$$)
14091{
14092 my ($T1, $T2, $V1, $V2) = @_;
14093 $T1 = uncover_typedefs($T1, $V1);
14094 $T2 = uncover_typedefs($T2, $V2);
14095 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
14096}
14097
14098sub addedQual($$$)
14099{
14100 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014101 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014102}
14103
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014104sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014105{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014106 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014107 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014108}
14109
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014110sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014111{
14112 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
14113 $Old_Value = uncover_typedefs($Old_Value, $V1);
14114 $New_Value = uncover_typedefs($New_Value, $V2);
14115 if($Old_Value eq $New_Value)
14116 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014117 return 0;
14118 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014119 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014120 { # without a qual
14121 return 0;
14122 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014123 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014124 { # became non-qual
14125 return 1;
14126 }
14127 else
14128 {
14129 my @BQ1 = getQualModel($Old_Value, $Qual);
14130 my @BQ2 = getQualModel($New_Value, $Qual);
14131 foreach (0 .. $#BQ1)
14132 { # removed qual
14133 if($BQ1[$_]==1
14134 and $BQ2[$_]!=1)
14135 {
14136 return 2;
14137 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014138 }
14139 }
14140 return 0;
14141}
14142
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014143sub getQualModel($$)
14144{
14145 my ($Value, $Qual) = @_;
14146 if(not $Qual) {
14147 return $Value;
14148 }
14149
14150 # cleaning
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014151 while($Value=~/(\w+)/ and $1 ne $Qual) {
14152 $Value=~s/\b$1\b//g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014153 }
14154 $Value=~s/[^\*\&\w]+//g;
14155
14156 # modeling
14157 # int*const*const == 011
14158 # int**const == 001
14159 my @Model = ();
14160 my @Elems = split(/[\*\&]/, $Value);
14161 if(not @Elems) {
14162 return (0);
14163 }
14164 foreach (@Elems)
14165 {
14166 if($_ eq $Qual) {
14167 push(@Model, 1);
14168 }
14169 else {
14170 push(@Model, 0);
14171 }
14172 }
14173
14174 return @Model;
14175}
14176
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014177my %StringTypes = map {$_=>1} (
14178 "char*",
14179 "char const*"
14180);
14181
14182my %CharTypes = map {$_=>1} (
14183 "char",
14184 "char const"
14185);
14186
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014187sub showVal($$$)
14188{
14189 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014190 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040014191 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014192 if(substr($Value, 0, 2) eq "_Z")
14193 {
14194 if(my $Unmangled = $tr_name{$Value}) {
14195 return $Unmangled;
14196 }
14197 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014198 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014199 { # strings
14200 return "\"$Value\"";
14201 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014202 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014203 { # characters
14204 return "\'$Value\'";
14205 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014206 if($Value eq "")
14207 { # other
14208 return "\'\'";
14209 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014210 return $Value;
14211}
14212
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014213sub getRegs($$$)
14214{
14215 my ($LibVersion, $Symbol, $Pos) = @_;
14216
14217 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
14218 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014219 my %Regs = ();
14220 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
14221 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014222 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014223 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
14224 }
14225 }
14226
14227 return join(", ", sort keys(%Regs));
14228 }
14229
14230 return undef;
14231}
14232
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014233sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014234{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014235 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014236 if(not $Symbol) {
14237 return;
14238 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014239 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
14240 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
14241 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
14242 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014243 if(not $PType1_Id
14244 or not $PType2_Id) {
14245 return;
14246 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014247
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014248 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014249 { # do not merge "this"
14250 if($PName1 eq "this" or $PName2 eq "this") {
14251 return;
14252 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014253 }
14254
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014255 my %Type1 = get_Type($PType1_Id, 1);
14256 my %Type2 = get_Type($PType2_Id, 2);
14257 my %BaseType1 = get_BaseType($PType1_Id, 1);
14258 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014259 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014260
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014261 if($Level eq "Binary")
14262 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014263 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014264 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
14265 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14266 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14267 {
14268 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014269 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014270 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014271 }
14272 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14273 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14274 {
14275 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014276 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014277 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014278 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014279 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014280
14281 if(defined $UsedDump{1}{"DWARF"}
14282 and defined $UsedDump{2}{"DWARF"})
14283 {
14284 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
14285 {
14286 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
14287 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
14288 if($Old_Regs and $New_Regs)
14289 {
14290 if($Old_Regs ne $New_Regs)
14291 {
14292 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
14293 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014294 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014295 "Old_Value"=>$Old_Regs,
14296 "New_Value"=>$New_Regs );
14297 }
14298 }
14299 elsif($Old_Regs and not $New_Regs)
14300 {
14301 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
14302 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014303 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014304 "Old_Value"=>$Old_Regs );
14305 }
14306 elsif(not $Old_Regs and $New_Regs)
14307 {
14308 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
14309 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014310 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014311 "New_Value"=>$New_Regs );
14312 }
14313 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
14314 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
14315 {
14316 if($Old_Offset ne $New_Offset)
14317 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014318 my $Start1 = $CompleteSignature{1}{$Symbol}{"Param"}{0}{"offset"};
14319 my $Start2 = $CompleteSignature{2}{$Symbol}{"Param"}{0}{"offset"};
14320
14321 $Old_Offset = $Old_Offset - $Start1;
14322 $New_Offset = $New_Offset - $Start2;
14323
14324 if($Old_Offset ne $New_Offset)
14325 {
14326 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
14327 "Target"=>$PName1,
14328 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14329 "Old_Value"=>$Old_Offset,
14330 "New_Value"=>$New_Offset );
14331 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014332 }
14333 }
14334 }
14335 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014336 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014337 if(checkDump(1, "2.0") and checkDump(2, "2.0")
14338 and $UsedDump{1}{"V"} ne "3.1" and $UsedDump{2}{"V"} ne "3.1")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014339 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014340 # broken in 3.1, fixed in 3.2
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014341 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
14342 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014343 if(not checkDump(1, "2.13")
14344 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014345 { # support for old ABI dumps
14346 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014347 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014348 if($Type1{"Name"} eq "bool"
14349 and $Value_Old eq "false" and $Value_New eq "0")
14350 { # int class::method ( bool p = 0 );
14351 # old ABI dumps: "false"
14352 # new ABI dumps: "0"
14353 $Value_Old = "0";
14354 }
14355 }
14356 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014357 if(not checkDump(1, "2.18")
14358 and checkDump(2, "2.18"))
14359 { # support for old ABI dumps
14360 if(not defined $Value_Old
14361 and substr($Value_New, 0, 2) eq "_Z") {
14362 $Value_Old = $Value_New;
14363 }
14364 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014365 if(defined $Value_Old)
14366 {
14367 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
14368 if(defined $Value_New)
14369 {
14370 $Value_New = showVal($Value_New, $PType2_Id, 2);
14371 if($Value_Old ne $Value_New)
14372 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014373 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014374 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014375 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014376 "Old_Value"=>$Value_Old,
14377 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014378 }
14379 }
14380 else
14381 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014382 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014383 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014384 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014385 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014386 }
14387 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014388 elsif(defined $Value_New)
14389 {
14390 $Value_New = showVal($Value_New, $PType2_Id, 2);
14391 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
14392 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014393 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014394 "New_Value"=>$Value_New );
14395 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014396 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014397
14398 if($ChkRnmd)
14399 {
14400 if($PName1 and $PName2 and $PName1 ne $PName2
14401 and $PType1_Id!=-1 and $PType2_Id!=-1
14402 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
14403 { # except unnamed "..." value list (Id=-1)
14404 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
14405 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014406 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014407 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
14408 "Old_Value"=>$PName1,
14409 "New_Value"=>$PName2,
14410 "New_Signature"=>get_Signature($Symbol, 2) );
14411 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014412 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014413
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014414 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014415 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014416
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014417 foreach my $SubProblemType (keys(%SubProblems))
14418 { # add new problems, remove false alarms
14419 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14420 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014421
14422 # quals
14423 if($SubProblemType eq "Parameter_Type"
14424 or $SubProblemType eq "Parameter_Type_And_Size"
14425 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014426 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014427 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014428 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014429 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014430 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014431 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014432 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
14433 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
14434 }
14435 }
14436 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
14437 {
14438 if(removedQual($Old_Value, $New_Value, "volatile")) {
14439 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014440 }
14441 }
14442 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
14443 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14444 { # int to "int const"
14445 delete($SubProblems{$SubProblemType});
14446 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014447 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014448 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14449 { # "int const" to int
14450 delete($SubProblems{$SubProblemType});
14451 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014452 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
14453 { # "const" to non-"const"
14454 if($RR==2) {
14455 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
14456 }
14457 else {
14458 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
14459 }
14460 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014461 }
14462 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014463
14464 if($Level eq "Source")
14465 {
14466 foreach my $SubProblemType (keys(%SubProblems))
14467 {
14468 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14469 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
14470
14471 if($SubProblemType eq "Parameter_Type")
14472 {
14473 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
14474 delete($SubProblems{$SubProblemType});
14475 }
14476 }
14477 }
14478 }
14479
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014480 foreach my $SubProblemType (keys(%SubProblems))
14481 { # modify/register problems
14482 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14483 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014484 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
14485 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014486
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014487 my $NewProblemType = $SubProblemType;
14488 if($Old_Value eq "..." and $New_Value ne "...")
14489 { # change from "..." to "int"
14490 if($ParamPos1==0)
14491 { # ISO C requires a named argument before "..."
14492 next;
14493 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014494 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014495 }
14496 elsif($New_Value eq "..." and $Old_Value ne "...")
14497 { # change from "int" to "..."
14498 if($ParamPos2==0)
14499 { # ISO C requires a named argument before "..."
14500 next;
14501 }
14502 $NewProblemType = "Parameter_Became_VaList";
14503 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014504 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014505 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014506 {
14507 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014508 if($Arch1 eq "unknown"
14509 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014510 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014511 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014512 ($Arch1, $Arch2) = ("unknown", "unknown");
14513 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014514 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014515 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014516 { # real
14517 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
14518 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
14519 }
14520 else
14521 { # model
14522 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
14523 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
14524 }
14525 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014526 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014527 if($Conv1{"Method"} eq "stack")
14528 {
14529 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
14530 $NewProblemType = "Parameter_Type_And_Stack";
14531 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014532 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014533 elsif($Conv1{"Method"} eq "reg")
14534 {
14535 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
14536 $NewProblemType = "Parameter_Type_And_Register";
14537 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014538 }
14539 }
14540 else
14541 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014542 if($Conv1{"Method"} eq "stack") {
14543 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014544 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014545 elsif($Conv1{"Method"} eq "register") {
14546 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014547 }
14548 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014549 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
14550 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014551 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014552 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014553 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014554 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014555 "New_Signature"=>get_Signature($Symbol, 2) );
14556 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014557 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014558
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014559 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014560
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014561 # checking type definition changes
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014562 my $Sub_SubProblems = mergeTypes($PType1_Id, $PType2_Id, $Level);
14563 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014564 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014565 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014566 {
14567 my $NewProblemType = $SubProblemType;
14568 if($SubProblemType eq "DataType_Size")
14569 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014570 if($Type1{"Type"}!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014571 { # stack has been affected
14572 $NewProblemType = "DataType_Size_And_Stack";
14573 }
14574 }
14575 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014576 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014577 }
14578 }
14579}
14580
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014581sub find_ParamPair_Pos_byName($$$)
14582{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014583 my ($Name, $Symbol, $LibVersion) = @_;
14584 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014585 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014586 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14587 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014588 {
14589 return $ParamPos;
14590 }
14591 }
14592 return "lost";
14593}
14594
14595sub find_ParamPair_Pos_byTypeAndPos($$$$$)
14596{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014597 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014598 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014599 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014600 {
14601 next if($Order eq "backward" and $ParamPos>$MediumPos);
14602 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014603 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14604 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014605 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014606 push(@Positions, $ParamPos);
14607 }
14608 }
14609 return @Positions;
14610}
14611
14612sub getTypeIdByName($$)
14613{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040014614 my ($TypeName, $LibVersion) = @_;
14615 return $TName_Tid{$LibVersion}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014616}
14617
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014618sub diffTypes($$$)
14619{
14620 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
14621 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
14622 }
14623 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
14624 { # skip recursive declarations
14625 return 0;
14626 }
14627
14628 pushType($_[0], $_[1], \@RecurTypes_Diff);
14629 my $Diff = diffTypes_I(@_);
14630 pop(@RecurTypes_Diff);
14631
14632 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
14633}
14634
14635sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014636{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014637 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014638
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014639 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14640 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014641
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014642 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
14643 { # equal types
14644 return 0;
14645 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014646 if($Type1_Pure{"Name"} eq "void")
14647 { # from void* to something
14648 return 0;
14649 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014650 if($Type1_Pure{"Name"}=~/\*/
14651 or $Type2_Pure{"Name"}=~/\*/)
14652 { # compared in detectTypeChange()
14653 return 0;
14654 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014655
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014656 my %FloatType = map {$_=>1} (
14657 "float",
14658 "double",
14659 "long double"
14660 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014661
14662 my $T1 = $Type1_Pure{"Type"};
14663 my $T2 = $Type2_Pure{"Type"};
14664
14665 if($T1 eq "Struct"
14666 and $T2 eq "Class")
14667 { # compare as data structures
14668 $T2 = "Struct";
14669 }
14670
14671 if($T1 eq "Class"
14672 and $T2 eq "Struct")
14673 { # compare as data structures
14674 $T1 = "Struct";
14675 }
14676
14677 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014678 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014679 if($T1 eq "Intrinsic"
14680 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014681 { # "int" to "enum"
14682 return 0;
14683 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014684 elsif($T2 eq "Intrinsic"
14685 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014686 { # "enum" to "int"
14687 return 0;
14688 }
14689 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014690 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014691 # ...
14692 return 1;
14693 }
14694 }
14695 else
14696 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014697 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014698 {
14699 if($FloatType{$Type1_Pure{"Name"}}
14700 or $FloatType{$Type2_Pure{"Name"}})
14701 { # "float" to "double"
14702 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014703 if($Level eq "Source")
14704 { # Safe
14705 return 0;
14706 }
14707 else {
14708 return 1;
14709 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014710 }
14711 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014712 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014713 {
14714 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14715 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014716 if(not @Membs1
14717 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014718 { # private
14719 return 0;
14720 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014721 if($#Membs1!=$#Membs2)
14722 { # different number of elements
14723 return 1;
14724 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014725 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014726 {
14727 foreach my $Pos (@Membs1)
14728 { # compare elements by name and value
14729 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14730 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14731 { # different names
14732 return 1;
14733 }
14734 }
14735 }
14736 else
14737 {
14738 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014739 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014740 if($Level eq "Source")
14741 {
14742 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14743 { # different names
14744 return 1;
14745 }
14746 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014747
14748 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14749 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14750
14751 if($MT1{"Name"} ne $MT2{"Name"}
14752 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14753 {
14754 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14755 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14756
14757 if($PL1 ne $PL2)
14758 { # different pointer level
14759 return 1;
14760 }
14761
14762 # compare base types
14763 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14764 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14765
14766 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14767 { # different types
14768 return 1;
14769 }
14770 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014771 }
14772 }
14773 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014774 else
14775 {
14776 # TODO: arrays, etc.
14777 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014778 }
14779 return 0;
14780}
14781
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014782sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014783{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014784 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014785 if(not $Type1_Id or not $Type2_Id) {
14786 return ();
14787 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014788 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014789 my %Type1 = get_Type($Type1_Id, 1);
14790 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014791 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14792 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
14793 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14794 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 +040014795
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014796 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14797 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014798 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14799 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14800 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14801 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14802 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14803 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14804 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014805 if($Type1{"Name"} eq $Type2{"Name"})
14806 {
14807 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14808 { # will be reported in mergeTypes() as typedef problem
14809 return ();
14810 }
14811 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14812 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14813 if(%Typedef_1 and %Typedef_2)
14814 {
14815 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14816 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14817 { # const Typedef
14818 return ();
14819 }
14820 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014821 }
14822 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14823 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014824 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014825 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14826 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014827 {
14828 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14829 "Old_Value"=>$Type1_Base{"Name"},
14830 "New_Value"=>$Type2_Base{"Name"},
14831 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014832 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014833 }
14834 else
14835 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014836 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014837 { # format change
14838 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14839 "Old_Value"=>$Type1_Base{"Name"},
14840 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014841 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014842 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014843 }
14844 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14845 {
14846 %{$LocalProblems{$Prefix."_BaseType"}}=(
14847 "Old_Value"=>$Type1_Base{"Name"},
14848 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014849 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014850 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014851 }
14852 }
14853 }
14854 }
14855 elsif($Type1{"Name"} ne $Type2{"Name"})
14856 { # type change
14857 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14858 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014859 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014860 and $Type1_Pure{"Name"} eq "void")
14861 {
14862 %{$LocalProblems{"Return_Type_From_Void"}}=(
14863 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014864 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014865 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014866 elsif($Prefix eq "Return"
14867 and $Type2_Pure{"Name"} eq "void")
14868 {
14869 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14870 "Old_Value"=>$Type1{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014871 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014872 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014873 else
14874 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014875 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014876 and $Type1{"Size"} and $Type2{"Size"}
14877 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014878 {
14879 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14880 "Old_Value"=>$Type1{"Name"},
14881 "New_Value"=>$Type2{"Name"},
14882 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014883 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014884 }
14885 else
14886 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014887 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014888 { # format change
14889 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14890 "Old_Value"=>$Type1{"Name"},
14891 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014892 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014893 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014894 }
14895 elsif(tNameLock($Type1_Id, $Type2_Id))
14896 { # FIXME: correct this condition
14897 %{$LocalProblems{$Prefix."_Type"}}=(
14898 "Old_Value"=>$Type1{"Name"},
14899 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014900 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014901 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014902 }
14903 }
14904 }
14905 }
14906 }
14907 if($Type1_PLevel!=$Type2_PLevel)
14908 {
14909 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14910 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14911 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014912 if($Level eq "Source")
14913 {
14914 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014915 "Old_Value"=>$Type1_PLevel,
14916 "New_Value"=>$Type2_PLevel);
14917 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014918 else
14919 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014920 if($Type2_PLevel>$Type1_PLevel)
14921 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014922 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
14923 "Old_Value"=>$Type1_PLevel,
14924 "New_Value"=>$Type2_PLevel);
14925 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014926 else
14927 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014928 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
14929 "Old_Value"=>$Type1_PLevel,
14930 "New_Value"=>$Type2_PLevel);
14931 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014932 }
14933 }
14934 }
Andrey Ponomarenkoac687f92013-08-01 18:53:30 +040014935 if($Type1_Pure{"Type"} eq "Array"
14936 and $Type1_Pure{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014937 { # base_type[N] -> base_type[N]
14938 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014939 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014940 foreach my $SubProblemType (keys(%SubProblems))
14941 {
14942 $SubProblemType=~s/_Type/_BaseType/g;
14943 next if(defined $LocalProblems{$SubProblemType});
14944 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
14945 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
14946 }
14947 }
14948 }
14949 return %LocalProblems;
14950}
14951
14952sub tNameLock($$)
14953{
14954 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014955 my $Changed = 0;
14956 if(differentDumps("G"))
14957 { # different GCC versions
14958 $Changed = 1;
14959 }
14960 elsif(differentDumps("V"))
14961 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014962 if(not checkDump(1, "2.20")
14963 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014964 { # latest names update
14965 # 2.6: added restrict qualifier
14966 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014967 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014968 $Changed = 1;
14969 }
14970 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014971
14972 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
14973 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
14974
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014975 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
14976 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
14977
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014978 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014979 { # different formats
14980 if($UseOldDumps)
14981 { # old dumps
14982 return 0;
14983 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014984
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014985 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014986 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014987 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014988 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014989 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014990 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014991 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014992 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014993 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
14994 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
14995 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014996 { # equal base types
14997 return 0;
14998 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014999
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015000 if(not checkDump(1, "2.13")
15001 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015002 { # broken array names in ABI dumps < 2.13
15003 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015004 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015005 return 0;
15006 }
15007 }
15008
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015009 if(not checkDump(1, "2.6")
15010 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015011 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015012 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015013 and $TN2=~/\brestrict\b/) {
15014 return 0;
15015 }
15016 }
15017
15018 if(not checkDump(1, "2.20")
15019 or not checkDump(2, "2.20"))
15020 { # added restrict attribute in 2.6
15021 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
15022 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015023 return 0;
15024 }
15025 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015026 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015027 else
15028 {
15029 # typedef struct {...} type_t
15030 # typedef struct type_t {...} type_t
15031 if(index($TN1, " ".$TN2)!=-1)
15032 {
15033 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
15034 return 0;
15035 }
15036 }
15037 if(index($TN2, " ".$TN1)!=-1)
15038 {
15039 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
15040 return 0;
15041 }
15042 }
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040015043
15044 if($TT1 eq "FuncPtr"
15045 and $TT2 eq "FuncPtr")
15046 {
15047 my $TN1_C = $TN1;
15048 my $TN2_C = $TN2;
15049
15050 $TN1_C=~s/\b(struct|union) //g;
15051 $TN2_C=~s/\b(struct|union) //g;
15052
15053 if($TN1_C eq $TN2_C) {
15054 return 0;
15055 }
15056 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015057 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015058 return 1;
15059}
15060
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015061sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015062{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015063 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015064 if(defined $Cache{"differentDumps"}{$Check}) {
15065 return $Cache{"differentDumps"}{$Check};
15066 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015067 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015068 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015069 if($Check eq "G")
15070 {
15071 if(getGccVersion(1) ne getGccVersion(2))
15072 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015073 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015074 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015075 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015076 if($Check eq "V")
15077 {
15078 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
15079 formatVersion($UsedDump{2}{"V"}, 2))!=0)
15080 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015081 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015082 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015083 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015084 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015085 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015086}
15087
15088sub formatVersion($$)
15089{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015090 my ($V, $Digits) = @_;
15091 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015092 return join(".", splice(@Elems, 0, $Digits));
15093}
15094
15095sub htmlSpecChars($)
15096{
15097 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015098 if(not $Str) {
15099 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015100 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015101 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15102 $Str=~s/</&lt;/g;
15103 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
15104 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015105 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
15106 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015107 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015108 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015109 $Str=~s/\n/<br\/>/g;
15110 $Str=~s/\"/&quot;/g;
15111 $Str=~s/\'/&#39;/g;
15112 return $Str;
15113}
15114
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015115sub xmlSpecChars($)
15116{
15117 my $Str = $_[0];
15118 if(not $Str) {
15119 return $Str;
15120 }
15121
15122 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15123 $Str=~s/</&lt;/g;
15124 $Str=~s/>/&gt;/g;
15125
15126 $Str=~s/\"/&quot;/g;
15127 $Str=~s/\'/&#39;/g;
15128
15129 return $Str;
15130}
15131
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040015132sub xmlSpecChars_R($)
15133{
15134 my $Str = $_[0];
15135 if(not $Str) {
15136 return $Str;
15137 }
15138
15139 $Str=~s/&amp;/&/g;
15140 $Str=~s/&lt;/</g;
15141 $Str=~s/&gt;/>/g;
15142
15143 $Str=~s/&quot;/"/g;
15144 $Str=~s/&#39;/'/g;
15145
15146 return $Str;
15147}
15148
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015149sub black_name($)
15150{
15151 my $Name = $_[0];
15152 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
15153}
15154
15155sub highLight_Signature($)
15156{
15157 my $Signature = $_[0];
15158 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
15159}
15160
15161sub highLight_Signature_Italic_Color($)
15162{
15163 my $Signature = $_[0];
15164 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
15165}
15166
15167sub separate_symbol($)
15168{
15169 my $Symbol = $_[0];
15170 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
15171 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
15172 ($Name, $Spec, $Ver) = ($1, $2, $3);
15173 }
15174 return ($Name, $Spec, $Ver);
15175}
15176
15177sub cut_f_attrs($)
15178{
15179 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
15180 return $2;
15181 }
15182 return "";
15183}
15184
15185sub highLight_Signature_PPos_Italic($$$$$)
15186{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015187 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
15188 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015189 if($CheckObjectsOnly) {
15190 $ItalicParams=$ColorParams=0;
15191 }
15192 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
15193 my $Return = "";
15194 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
15195 $Return = $2;
15196 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015197 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015198 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015199 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015200 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015201 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015202 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015203 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015204 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015205 }
15206 return $Signature;
15207 }
15208 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
15209 $Begin.=" " if($Begin!~/ \Z/);
15210 $End = cut_f_attrs($Signature);
15211 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015212 my ($Short, $Params) = split_Signature($Signature);
15213 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015214 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015215 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015216 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015217 $Part=~s/\A\s+|\s+\Z//g;
15218 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
15219 if($Part=~/\([\*]+(\w+)\)/i) {
15220 $ParamName = $1;#func-ptr
15221 }
15222 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
15223 $ParamName = $1;
15224 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015225 if(not $ParamName)
15226 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015227 push(@Parts, $Part_Styled);
15228 next;
15229 }
15230 if($ItalicParams and not $TName_Tid{1}{$Part}
15231 and not $TName_Tid{2}{$Part})
15232 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015233 my $Style = "param";
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015234 if($Param_Pos ne ""
15235 and $Pos==$Param_Pos) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015236 $Style = "focus_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015237 }
15238 elsif($ColorParams) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015239 $Style = "color_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015240 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015241 $Part_Styled =~ s!(\W)$ParamName([\,\)]|\Z)!$1<span class=\'$Style\'>$ParamName</span>$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015242 }
15243 $Part_Styled=~s/,(\w)/, $1/g;
15244 push(@Parts, $Part_Styled);
15245 }
15246 if(@Parts)
15247 {
15248 foreach my $Num (0 .. $#Parts)
15249 {
15250 if($Num==$#Parts)
15251 { # add ")" to the last parameter
15252 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
15253 }
15254 elsif(length($Parts[$Num])<=45) {
15255 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
15256 }
15257 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015258 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015259 }
15260 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015261 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015262 }
15263 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015264 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015265 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015266 $Signature=~s!\[\]![&#160;]!g;
15267 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015268 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
15269 if($SymbolVersion) {
15270 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
15271 }
15272 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015273}
15274
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015275sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015276{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015277 my $Signature = $_[0];
15278 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
15279 {
15280 $Signature=~s/\A\Q$ShortName\E\(//g;
15281 cut_f_attrs($Signature);
15282 $Signature=~s/\)\Z//;
15283 return ($ShortName, $Signature);
15284 }
15285
15286 # error
15287 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015288}
15289
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015290sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015291{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015292 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015293 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015294 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15295 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015296 foreach my $Pos (0 .. length($Params) - 1)
15297 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015298 my $S = substr($Params, $Pos, 1);
15299 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015300 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015301 }
15302 if($S eq "," and
15303 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015304 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015305 if($Comma)
15306 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015307 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015308 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015309 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015310 }
15311 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015312 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015313 }
15314 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015315 if(not $Sp)
15316 { # remove spaces
15317 foreach (@Parts)
15318 {
15319 s/\A //g;
15320 s/ \Z//g;
15321 }
15322 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015323 return @Parts;
15324}
15325
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015326sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015327{
15328 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015329 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015330 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015331 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15332 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015333 $Center+=length($1);
15334 }
15335 foreach my $Pos (0 .. length($Sign)-1)
15336 {
15337 my $S = substr($Sign, $Pos, 1);
15338 if($S eq $Target)
15339 {
15340 if($B{"("}==$B{")"}
15341 and $B{"<"}==$B{">"}) {
15342 return $Center;
15343 }
15344 }
15345 if(defined $B{$S}) {
15346 $B{$S}+=1;
15347 }
15348 $Center+=1;
15349 }
15350 return 0;
15351}
15352
15353sub appendFile($$)
15354{
15355 my ($Path, $Content) = @_;
15356 return if(not $Path);
15357 if(my $Dir = get_dirname($Path)) {
15358 mkpath($Dir);
15359 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015360 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015361 print FILE $Content;
15362 close(FILE);
15363}
15364
15365sub writeFile($$)
15366{
15367 my ($Path, $Content) = @_;
15368 return if(not $Path);
15369 if(my $Dir = get_dirname($Path)) {
15370 mkpath($Dir);
15371 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015372 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015373 print FILE $Content;
15374 close(FILE);
15375}
15376
15377sub readFile($)
15378{
15379 my $Path = $_[0];
15380 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015381 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015382 local $/ = undef;
15383 my $Content = <FILE>;
15384 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015385 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015386 $Content=~s/\r/\n/g;
15387 }
15388 return $Content;
15389}
15390
15391sub get_filename($)
15392{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015393 if(defined $Cache{"get_filename"}{$_[0]}) {
15394 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015395 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015396 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15397 return ($Cache{"get_filename"}{$_[0]}=$1);
15398 }
15399 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015400}
15401
15402sub get_dirname($)
15403{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015404 if(defined $Cache{"get_dirname"}{$_[0]}) {
15405 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015406 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015407 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15408 return ($Cache{"get_dirname"}{$_[0]}=$1);
15409 }
15410 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015411}
15412
15413sub separate_path($) {
15414 return (get_dirname($_[0]), get_filename($_[0]));
15415}
15416
15417sub esc($)
15418{
15419 my $Str = $_[0];
15420 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15421 return $Str;
15422}
15423
15424sub readLineNum($$)
15425{
15426 my ($Path, $Num) = @_;
15427 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015428 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015429 foreach (1 ... $Num) {
15430 <FILE>;
15431 }
15432 my $Line = <FILE>;
15433 close(FILE);
15434 return $Line;
15435}
15436
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015437sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015438{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015439 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015440 return () if(not $Path or not -f $Path);
15441 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015442 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15443 {
15444 foreach my $AttrVal (split(/;/, $1))
15445 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015446 if($AttrVal=~/(.+):(.+)/)
15447 {
15448 my ($Name, $Value) = ($1, $2);
15449 $Attributes{$Name} = $Value;
15450 }
15451 }
15452 }
15453 return \%Attributes;
15454}
15455
15456sub is_abs($) {
15457 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15458}
15459
15460sub get_abs_path($)
15461{ # abs_path() should NOT be called for absolute inputs
15462 # because it can change them
15463 my $Path = $_[0];
15464 if(not is_abs($Path)) {
15465 $Path = abs_path($Path);
15466 }
15467 return $Path;
15468}
15469
15470sub get_OSgroup()
15471{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015472 my $N = $Config{"osname"};
15473 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015474 return "macos";
15475 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015476 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015477 return "bsd";
15478 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015479 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015480 return "beos";
15481 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015482 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015483 return "symbian";
15484 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015485 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015486 return "windows";
15487 }
15488 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015489 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015490 }
15491}
15492
15493sub getGccVersion($)
15494{
15495 my $LibVersion = $_[0];
15496 if($GCC_VERSION{$LibVersion})
15497 { # dump version
15498 return $GCC_VERSION{$LibVersion};
15499 }
15500 elsif($UsedDump{$LibVersion}{"V"})
15501 { # old-version dumps
15502 return "unknown";
15503 }
15504 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15505 if(not $GccVersion) {
15506 return "unknown";
15507 }
15508 return $GccVersion;
15509}
15510
15511sub showArch($)
15512{
15513 my $Arch = $_[0];
15514 if($Arch eq "arm"
15515 or $Arch eq "mips") {
15516 return uc($Arch);
15517 }
15518 return $Arch;
15519}
15520
15521sub getArch($)
15522{
15523 my $LibVersion = $_[0];
15524 if($CPU_ARCH{$LibVersion})
15525 { # dump version
15526 return $CPU_ARCH{$LibVersion};
15527 }
15528 elsif($UsedDump{$LibVersion}{"V"})
15529 { # old-version dumps
15530 return "unknown";
15531 }
15532 if(defined $Cache{"getArch"}{$LibVersion}) {
15533 return $Cache{"getArch"}{$LibVersion};
15534 }
15535 my $Arch = get_dumpmachine($GCC_PATH); # host version
15536 if(not $Arch) {
15537 return "unknown";
15538 }
15539 if($Arch=~/\A([\w]{3,})(-|\Z)/) {
15540 $Arch = $1;
15541 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040015542 $Arch = "x86" if($Arch=~/\Ai[3-7]86\Z/i);
15543 $Arch = "x86_64" if($Arch=~/\Aamd64\Z/i);
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040015544 if($OSgroup eq "windows")
15545 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015546 $Arch = "x86" if($Arch=~/win32|mingw32/i);
15547 $Arch = "x86_64" if($Arch=~/win64|mingw64/i);
15548 }
15549 $Cache{"getArch"}{$LibVersion} = $Arch;
15550 return $Arch;
15551}
15552
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015553sub get_Report_Header($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015554{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015555 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015556 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015557 if(getArch(1) ne getArch(2)
15558 or getArch(1) eq "unknown"
15559 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015560 { # don't show architecture in the header
15561 $ArchInfo="";
15562 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015563 my $Report_Header = "<h1><span class='nowrap'>";
15564 if($Level eq "Source") {
15565 $Report_Header .= "Source compatibility";
15566 }
15567 elsif($Level eq "Binary") {
15568 $Report_Header .= "Binary compatibility";
15569 }
15570 else {
15571 $Report_Header .= "API compatibility";
15572 }
15573 $Report_Header .= " report for the <span style='color:Blue;'>$TargetLibraryFName</span> $TargetComponent</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015574 $Report_Header .= " <span class='nowrap'>&#160;between <span style='color:Red;'>".$Descriptor{1}{"Version"}."</span> and <span style='color:Red;'>".$Descriptor{2}{"Version"}."</span> versions$ArchInfo</span>";
15575 if($AppPath) {
15576 $Report_Header .= " <span class='nowrap'>&#160;(relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)</span>";
15577 }
15578 $Report_Header .= "</h1>\n";
15579 return $Report_Header;
15580}
15581
15582sub get_SourceInfo()
15583{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015584 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015585 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015586 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015587 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015588 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015589 $CheckedHeaders = "<a name='Headers'></a><h2>Header Files (".($#Headers+1).")</h2><hr/>\n";
15590 $CheckedHeaders .= "<div class='h_list'>\n";
15591 foreach my $Header_Path (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15592 {
15593 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15594 my $Name = get_filename($Identity);
15595 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15596 $CheckedHeaders .= $Name.$Comment."<br/>\n";
15597 }
15598 $CheckedHeaders .= "</div>\n";
15599 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015600 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015601
15602 if(my @Sources = keys(%{$Registered_Sources{1}}))
15603 {
15604 $CheckedSources = "<a name='Sources'></a><h2>Source Files (".($#Sources+1).")</h2><hr/>\n";
15605 $CheckedSources .= "<div class='h_list'>\n";
15606 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15607 {
15608 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15609 my $Name = get_filename($Identity);
15610 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15611 $CheckedSources .= $Name.$Comment."<br/>\n";
15612 }
15613 $CheckedSources .= "</div>\n";
15614 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15615 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015616 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015617 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015618 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015619 $CheckedLibs = "<a name='Libs'></a><h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2><hr/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015620 $CheckedLibs .= "<div class='lib_list'>\n";
15621 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15622 {
15623 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15624 $CheckedLibs .= $Library."<br/>\n";
15625 }
15626 $CheckedLibs .= "</div>\n";
15627 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015628 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015629 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15630}
15631
15632sub get_ObjTitle()
15633{
15634 if(defined $UsedDump{1}{"DWARF"}) {
15635 return "Objects";
15636 }
15637 else {
15638 return ucfirst($SLIB_TYPE)." Libraries";
15639 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015640}
15641
15642sub get_TypeProblems_Count($$$)
15643{
15644 my ($TypeChanges, $TargetPriority, $Level) = @_;
15645 my $Type_Problems_Count = 0;
15646 foreach my $Type_Name (sort keys(%{$TypeChanges}))
15647 {
15648 my %Kinds_Target = ();
15649 foreach my $Kind (keys(%{$TypeChanges->{$Type_Name}}))
15650 {
15651 foreach my $Location (keys(%{$TypeChanges->{$Type_Name}{$Kind}}))
15652 {
15653 my $Target = $TypeChanges->{$Type_Name}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015654 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
15655 next if($Severity ne $TargetPriority);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015656 if($Kinds_Target{$Kind}{$Target}) {
15657 next;
15658 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015659
15660 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target})
15661 {
15662 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
15663 { # select a problem with the highest priority
15664 next;
15665 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015666 }
15667 $Kinds_Target{$Kind}{$Target} = 1;
15668 $Type_Problems_Count += 1;
15669 }
15670 }
15671 }
15672 return $Type_Problems_Count;
15673}
15674
15675sub get_Summary($)
15676{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015677 my $Level = $_[0];
15678 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015679 $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 +040015680 %{$RESULT{$Level}} = (
15681 "Problems"=>0,
15682 "Warnings"=>0,
15683 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015684 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015685 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015686 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015687 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015688 {
15689 if(not defined $CompatRules{$Level}{$Kind})
15690 { # unknown rule
15691 if(not $UnknownRules{$Level}{$Kind})
15692 { # only one warning
15693 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15694 $UnknownRules{$Level}{$Kind}=1;
15695 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015696 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015697 }
15698 }
15699 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015700 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15701 {
15702 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15703 {
15704 if(not defined $CompatRules{$Level}{$Kind})
15705 { # unknown rule
15706 if(not $UnknownRules{$Level}{$Kind})
15707 { # only one warning
15708 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15709 $UnknownRules{$Level}{$Kind}=1;
15710 }
15711 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15712 }
15713 }
15714 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015715 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015716 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015717 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015718 {
15719 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15720 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015721 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015722 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015723 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015724 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015725 $Added += 1;
15726 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015727 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015728 {
15729 $Removed += 1;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015730 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015731 }
15732 else
15733 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015734 if($Severity eq "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015735 $I_Other += 1;
15736 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015737 elsif($Severity eq "High") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015738 $I_Problems_High += 1;
15739 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015740 elsif($Severity eq "Medium") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015741 $I_Problems_Medium += 1;
15742 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015743 elsif($Severity eq "Low") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015744 $I_Problems_Low += 1;
15745 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015746 if(($Severity ne "Low" or $StrictCompat)
15747 and $Severity ne "Safe") {
15748 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015749 }
15750 }
15751 }
15752 }
15753 }
15754 }
15755 my %TypeChanges = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015756 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015757 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015758 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015759 {
15760 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15761 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015762 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015763 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015764 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15765 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015766 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015767 my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target};
15768
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015769 if($MaxSeverity and $Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015770 { # select a problem with the highest priority
15771 next;
15772 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015773
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015774 if(($Severity ne "Low" or $StrictCompat)
15775 and $Severity ne "Safe")
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015776 {
15777 if(defined $TotalAffected{$Level}{$Interface})
15778 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015779 if($Severity_Val{$Severity}>$Severity_Val{$TotalAffected{$Level}{$Interface}}) {
15780 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015781 }
15782 }
15783 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015784 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015785 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015786 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015787
15788 $TypeChanges{$Type_Name}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
15789
15790 if($MaxSeverity)
15791 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015792 if($Severity_Val{$Severity}>$Severity_Val{$MaxSeverity}) {
15793 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015794 }
15795 }
15796 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015797 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015798 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015799 }
15800 }
15801 }
15802 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015803
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015804 $T_Problems_High = get_TypeProblems_Count(\%TypeChanges, "High", $Level);
15805 $T_Problems_Medium = get_TypeProblems_Count(\%TypeChanges, "Medium", $Level);
15806 $T_Problems_Low = get_TypeProblems_Count(\%TypeChanges, "Low", $Level);
15807 $T_Other = get_TypeProblems_Count(\%TypeChanges, "Safe", $Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015808
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015809 %TypeChanges = (); # free memory
15810
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015811 if($CheckObjectsOnly)
15812 { # only removed exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015813 $RESULT{$Level}{"Affected"} = $Removed*100/keys(%{$Symbol_Library{1}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015814 }
15815 else
15816 { # changed and removed public symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015817 my $SCount = keys(%{$CheckedSymbols{$Level}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015818 if($ExtendedCheck)
15819 { # don't count external_func_0 for constants
15820 $SCount-=1;
15821 }
15822 if($SCount)
15823 {
15824 my %Weight = (
15825 "High" => 100,
15826 "Medium" => 50,
15827 "Low" => 25
15828 );
15829 foreach (keys(%{$TotalAffected{$Level}})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015830 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015831 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015832 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015833 }
15834 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015835 $RESULT{$Level}{"Affected"} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015836 }
15837 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015838 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15839 if($RESULT{$Level}{"Affected"}>=100) {
15840 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015841 }
15842
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015843 $RESULT{$Level}{"Problems"} += $Removed;
15844 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015845 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015846 if($StrictCompat) {
15847 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15848 }
15849 else {
15850 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15851 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015852
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015853 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015854 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015855 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015856 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015857 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015858 if($Severity eq "Safe")
15859 {
15860 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015861 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015862 elsif($Severity eq "Low")
15863 {
15864 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015865 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015866 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015867 }
15868
15869 if($C_Problems_Low)
15870 {
15871 if($StrictCompat) {
15872 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
15873 }
15874 else {
15875 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015876 }
15877 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015878 if($CheckImpl and $Level eq "Binary")
15879 {
15880 if($StrictCompat) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015881 $RESULT{$Level}{"Problems"} += keys(%CompatProblems_Impl);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015882 }
15883 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015884 $RESULT{$Level}{"Warnings"} += keys(%CompatProblems_Impl);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015885 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015886 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015887 if($RESULT{$Level}{"Problems"}
15888 and $RESULT{$Level}{"Affected"}) {
15889 $RESULT{$Level}{"Verdict"} = "incompatible";
15890 }
15891 else {
15892 $RESULT{$Level}{"Verdict"} = "compatible";
15893 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015894
15895 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
15896 if(not $TotalTypes)
15897 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015898 $TotalTypes = keys(%{$TName_Tid{1}});
15899 }
15900
15901 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
15902 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
15903
15904 my ($TestInfo, $TestResults, $Problem_Summary) = ();
15905
15906 if($ReportFormat eq "xml")
15907 { # XML
15908 # test info
15909 $TestInfo .= " <library>$TargetLibraryName</library>\n";
15910 $TestInfo .= " <version1>\n";
15911 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
15912 $TestInfo .= " <architecture>$Arch1</architecture>\n";
15913 $TestInfo .= " <gcc>$GccV1</gcc>\n";
15914 $TestInfo .= " </version1>\n";
15915
15916 $TestInfo .= " <version2>\n";
15917 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
15918 $TestInfo .= " <architecture>$Arch2</architecture>\n";
15919 $TestInfo .= " <gcc>$GccV2</gcc>\n";
15920 $TestInfo .= " </version2>\n";
15921 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
15922
15923 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015924 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015925 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015926 $TestResults .= " <headers>\n";
15927 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15928 {
15929 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
15930 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15931 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15932 }
15933 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015934 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015935
15936 if(my @Sources = keys(%{$Registered_Sources{1}}))
15937 {
15938 $TestResults .= " <sources>\n";
15939 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15940 {
15941 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
15942 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15943 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15944 }
15945 $TestResults .= " </sources>\n";
15946 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015947
15948 $TestResults .= " <libs>\n";
15949 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15950 {
15951 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15952 $TestResults .= " <name>$Library</name>\n";
15953 }
15954 $TestResults .= " </libs>\n";
15955
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015956 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015957 $TestResults .= " <types>".$TotalTypes."</types>\n";
15958
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015959 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
15960 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015961 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
15962
15963 # problem summary
15964 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
15965 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
15966
15967 $Problem_Summary .= " <problems_with_types>\n";
15968 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
15969 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
15970 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
15971 $Problem_Summary .= " <safe>$T_Other</safe>\n";
15972 $Problem_Summary .= " </problems_with_types>\n";
15973
15974 $Problem_Summary .= " <problems_with_symbols>\n";
15975 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
15976 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
15977 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015978 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015979 $Problem_Summary .= " </problems_with_symbols>\n";
15980
15981 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015982 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015983 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015984 if($CheckImpl and $Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015985 {
15986 $Problem_Summary .= " <impl>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015987 $Problem_Summary .= " <low>".keys(%CompatProblems_Impl)."</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015988 $Problem_Summary .= " </impl>\n";
15989 }
15990 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
15991
15992 return ($TestInfo.$TestResults.$Problem_Summary, "");
15993 }
15994 else
15995 { # HTML
15996 # test info
15997 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015998 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015999 $TestInfo .= "<tr><th>".ucfirst($TargetComponent)." Name</th><td>$TargetLibraryFName</td></tr>\n";
16000
16001 my (@VInf1, @VInf2, $AddTestInfo) = ();
16002 if($Arch1 ne "unknown"
16003 and $Arch2 ne "unknown")
16004 { # CPU arch
16005 if($Arch1 eq $Arch2)
16006 { # go to the separate section
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016007 $AddTestInfo .= "<tr><th>CPU Type</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016008 }
16009 else
16010 { # go to the version number
16011 push(@VInf1, showArch($Arch1));
16012 push(@VInf2, showArch($Arch2));
16013 }
16014 }
16015 if($GccV1 ne "unknown"
16016 and $GccV2 ne "unknown"
16017 and $OStarget ne "windows")
16018 { # GCC version
16019 if($GccV1 eq $GccV2)
16020 { # go to the separate section
16021 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
16022 }
16023 else
16024 { # go to the version number
16025 push(@VInf1, "gcc ".$GccV1);
16026 push(@VInf2, "gcc ".$GccV2);
16027 }
16028 }
16029 # show long version names with GCC version and CPU architecture name (if different)
16030 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
16031 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
16032 $TestInfo .= $AddTestInfo;
16033 #if($COMMON_LANGUAGE{1}) {
16034 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
16035 #}
16036 if($ExtendedCheck) {
16037 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
16038 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016039 if($JoinReport)
16040 {
16041 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016042 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016043 }
16044 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016045 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016046 }
16047 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016048 $TestInfo .= "</table>\n";
16049
16050 # test results
16051 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016052 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016053
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016054 if(my @Headers = keys(%{$Registered_Headers{1}}))
16055 {
16056 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
16057 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
16058 }
16059 elsif($CheckObjectsOnly) {
16060 $TestResults .= "<tr><th>Total Header Files</th><td>0&#160;(not&#160;analyzed)</td></tr>\n";
16061 }
16062
16063 if(my @Sources = keys(%{$Registered_Sources{1}}))
16064 {
16065 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
16066 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
16067 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016068
16069 if(not $ExtendedCheck)
16070 {
16071 my $Libs_Link = "0";
16072 $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 +040016073 $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 +040016074 }
16075
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016076 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016077
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016078 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016079 if($JoinReport) {
16080 $META_DATA = "kind:".lc($Level).";".$META_DATA;
16081 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016082 $TestResults .= "<tr><th>Verdict</th>";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016083 if($RESULT{$Level}{"Verdict"} eq "incompatible") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016084 $TestResults .= "<td><span style='color:Red;'><b>Incompatible<br/>(".$RESULT{$Level}{"Affected"}."%)</b></span></td>";
16085 }
16086 else {
16087 $TestResults .= "<td><span style='color:Green;'><b>Compatible</b></span></td>";
16088 }
16089 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016090 $TestResults .= "</table>\n";
16091
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016092 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016093 # problem summary
16094 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016095 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016096 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
16097
16098 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016099 if($Added>0)
16100 {
16101 if($JoinReport) {
16102 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
16103 }
16104 else {
16105 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
16106 }
16107 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016108 $META_DATA .= "added:$Added;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016109 $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 +040016110
16111 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016112 if($Removed>0)
16113 {
16114 if($JoinReport) {
16115 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
16116 }
16117 else {
16118 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
16119 }
16120 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016121 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016122 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
16123 $Problem_Summary .= "<td>High</td><td".getStyle("I", "R", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016124
16125 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016126 $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 +040016127 $TH_Link = "n/a" if($CheckObjectsOnly);
16128 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016129 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
16130 $Problem_Summary .= "<td>High</td><td".getStyle("T", "H", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016131
16132 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016133 $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 +040016134 $TM_Link = "n/a" if($CheckObjectsOnly);
16135 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016136 $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 +040016137
16138 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016139 $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 +040016140 $TL_Link = "n/a" if($CheckObjectsOnly);
16141 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016142 $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 +040016143
16144 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016145 $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 +040016146 $IH_Link = "n/a" if($CheckObjectsOnly);
16147 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016148 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
16149 $Problem_Summary .= "<td>High</td><td".getStyle("I", "H", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016150
16151 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016152 $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 +040016153 $IM_Link = "n/a" if($CheckObjectsOnly);
16154 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016155 $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 +040016156
16157 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016158 $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 +040016159 $IL_Link = "n/a" if($CheckObjectsOnly);
16160 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016161 $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 +040016162
16163 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016164 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
16165 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016166 }
16167 $ChangedConstants_Link = "n/a" if($CheckObjectsOnly);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016168 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016169 $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 +040016170
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016171 if($CheckImpl and $Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016172 {
16173 my $ChangedImpl_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016174 $ChangedImpl_Link = "<a href='#Changed_Implementation' style='color:Blue;'>".keys(%CompatProblems_Impl)."</a>" if(keys(%CompatProblems_Impl)>0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016175 $ChangedImpl_Link = "n/a" if($CheckHeadersOnly);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016176 $META_DATA .= "changed_implementation:".keys(%CompatProblems_Impl).";";
16177 $Problem_Summary .= "<tr><th>Problems with<br/>Implementation</th><td>Low</td><td".getStyle("Imp", "L", int(keys(%CompatProblems_Impl))).">$ChangedImpl_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016178 }
16179 # Safe Changes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016180 if($T_Other and not $CheckObjectsOnly)
16181 {
16182 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016183 $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 +040016184 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016185
16186 if($I_Other and not $CheckObjectsOnly)
16187 {
16188 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016189 $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 +040016190 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016191
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016192 if($C_Other and not $CheckObjectsOnly)
16193 {
16194 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
16195 $Problem_Summary .= "<tr><th>Other Changes<br/>in Constants</th><td>-</td><td".getStyle("C", "S", $C_Other).">$CS_Link</td></tr>\n";
16196 }
16197
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016198 $META_DATA .= "tool_version:$TOOL_VERSION";
16199 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016200 # $TestInfo = getLegend().$TestInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016201 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
16202 }
16203}
16204
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016205sub getStyle($$$)
16206{
16207 my ($Subj, $Act, $Num) = @_;
16208 my %Style = (
16209 "A"=>"new",
16210 "R"=>"failed",
16211 "S"=>"passed",
16212 "L"=>"warning",
16213 "M"=>"failed",
16214 "H"=>"failed"
16215 );
16216 if($Num>0) {
16217 return " class='".$Style{$Act}."'";
16218 }
16219 return "";
16220}
16221
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016222sub show_number($)
16223{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016224 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016225 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016226 my $Num = cut_off_number($_[0], 2, 0);
16227 if($Num eq "0")
16228 {
16229 foreach my $P (3 .. 7)
16230 {
16231 $Num = cut_off_number($_[0], $P, 1);
16232 if($Num ne "0") {
16233 last;
16234 }
16235 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016236 }
16237 if($Num eq "0") {
16238 $Num = $_[0];
16239 }
16240 return $Num;
16241 }
16242 return $_[0];
16243}
16244
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016245sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016246{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016247 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016248 if($num!~/\./)
16249 {
16250 $num .= ".";
16251 foreach (1 .. $digs_to_cut-1) {
16252 $num .= "0";
16253 }
16254 }
16255 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
16256 {
16257 foreach (1 .. $digs_to_cut - 1 - length($1)) {
16258 $num .= "0";
16259 }
16260 }
16261 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
16262 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
16263 }
16264 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016265 if($z) {
16266 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
16267 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016268 return $num;
16269}
16270
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016271sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016272{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016273 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016274 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016275
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016276 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016277 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
16278 {
16279 my $Header = $Constants{1}{$Constant}{"Header"};
16280 if(not $Header)
16281 { # added
16282 $Header = $Constants{2}{$Constant}{"Header"}
16283 }
16284
16285 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16286 {
16287 if(not defined $CompatRules{$Level}{$Kind}) {
16288 next;
16289 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016290 if($TargetSeverity ne $CompatRules{$Level}{$Kind}{"Severity"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016291 next;
16292 }
16293 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16294 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016295 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016296
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016297 if($ReportFormat eq "xml")
16298 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016299 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016300 {
16301 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016302 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016303 {
16304 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016305 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16306 {
16307 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16308 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16309 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016310
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016311 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16312 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16313 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
16314 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16315 $CHANGED_CONSTANTS .= " </problem>\n";
16316 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016317 $CHANGED_CONSTANTS .= " </constant>\n";
16318 }
16319 $CHANGED_CONSTANTS .= " </header>\n";
16320 }
16321 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16322 }
16323 else
16324 { # HTML
16325 my $Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016326 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016327 {
16328 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016329 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016330 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016331 my $Report = "";
16332
16333 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16334 {
16335 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16336 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16337 $Report .= "<tr><th>1</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
16338 $Number += 1;
16339 }
16340 if($Report)
16341 {
16342 $Report = $ContentDivStart."<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>".$Report."</table><br/>$ContentDivEnd\n";
16343 $Report = $ContentSpanStart."<span class='extendable'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
16344 $Report = insertIDs($Report);
16345 }
16346 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016347 }
16348 $CHANGED_CONSTANTS .= "<br/>\n";
16349 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016350 if($CHANGED_CONSTANTS)
16351 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016352 my $Title = "Problems with Constants, $TargetSeverity Severity";
16353 if($TargetSeverity eq "Safe")
16354 { # Safe Changes
16355 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016356 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016357 $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 +040016358 }
16359 }
16360 return $CHANGED_CONSTANTS;
16361}
16362
16363sub get_Report_Impl()
16364{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016365 my $CHANGED_IMPLEMENTATION = "";
16366 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016367 foreach my $Interface (sort keys(%CompatProblems_Impl))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016368 {
16369 my $HeaderName = $CompleteSignature{1}{$Interface}{"Header"};
16370 my $DyLib = $Symbol_Library{1}{$Interface};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016371 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016372 }
16373 my $Changed_Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016374 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016375 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016376 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016377 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016378 my %NameSpaceSymbols = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016379 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016380 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016381 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016382 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016383 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016384 $CHANGED_IMPLEMENTATION .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016385 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016386 foreach my $Interface (@SortedInterfaces)
16387 {
16388 $Changed_Number += 1;
16389 my $Signature = get_Signature($Interface, 1);
16390 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016391 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016392 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016393 $CHANGED_IMPLEMENTATION .= $ContentSpanStart.highLight_Signature_Italic_Color($Signature).$ContentSpanEnd."<br/>\n".$ContentDivStart."<span class='mangled'>[symbol: <b>$Interface</b>]</span>".$CompatProblems_Impl{$Interface}{"Diff"}."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016394 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016395 $CHANGED_IMPLEMENTATION .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016396 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016397 }
16398 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016399 if($CHANGED_IMPLEMENTATION)
16400 {
16401 $CHANGED_IMPLEMENTATION = insertIDs($CHANGED_IMPLEMENTATION);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016402 $CHANGED_IMPLEMENTATION = "<a name='Changed_Implementation'></a><h2>Problems with Implementation ($Changed_Number)</h2><hr/>\n".$CHANGED_IMPLEMENTATION.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016403 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016404
16405 # clean memory
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016406 %CompatProblems_Impl = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016407
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016408 return $CHANGED_IMPLEMENTATION;
16409}
16410
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016411sub getTitle($$$)
16412{
16413 my ($Header, $Library, $NameSpace) = @_;
16414 my $Title = "";
16415 if($Library and $Library!~/\.\w+\Z/) {
16416 $Library .= " (.$LIB_EXT)";
16417 }
16418 if($Header and $Library)
16419 {
16420 $Title .= "<span class='h_name'>$Header</span>";
16421 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16422 }
16423 elsif($Library) {
16424 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16425 }
16426 elsif($Header) {
16427 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16428 }
16429 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016430 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016431 }
16432 return $Title;
16433}
16434
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016435sub get_Report_Added($)
16436{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016437 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016438 my $ADDED_INTERFACES = "";
16439 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016440 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016441 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016442 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016443 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016444 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016445 {
16446 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16447 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016448 if($Level eq "Source" and $ReportFormat eq "html")
16449 { # do not show library name in HTML report
16450 $DyLib = "";
16451 }
16452 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016453 }
16454 }
16455 }
16456 if($ReportFormat eq "xml")
16457 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016458 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016459 {
16460 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016461 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016462 {
16463 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016464 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016465 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16466 }
16467 $ADDED_INTERFACES .= " </library>\n";
16468 }
16469 $ADDED_INTERFACES .= " </header>\n";
16470 }
16471 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16472 }
16473 else
16474 { # HTML
16475 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016476 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016477 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016478 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016479 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016480 my %NameSpaceSymbols = ();
16481 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016482 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016483 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016484 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016485 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016486 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16487 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016488 foreach my $Interface (@SortedInterfaces)
16489 {
16490 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016491 my $Signature = get_Signature($Interface, 2);
16492 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016493 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016494 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016495 if($Interface=~/\A(_Z|\?)/)
16496 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016497 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016498 $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 +040016499 }
16500 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016501 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016502 }
16503 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016504 else
16505 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016506 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016507 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016508 }
16509 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016510 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016511 }
16512 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016513 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016514 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016515 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016516 }
16517 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016518 if($ADDED_INTERFACES)
16519 {
16520 my $Anchor = "<a name='Added'></a>";
16521 if($JoinReport) {
16522 $Anchor = "<a name='".$Level."_Added'></a>";
16523 }
16524 $ADDED_INTERFACES = $Anchor."<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016525 }
16526 }
16527 return $ADDED_INTERFACES;
16528}
16529
16530sub get_Report_Removed($)
16531{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016532 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016533 my $REMOVED_INTERFACES = "";
16534 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016535 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016536 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016537 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016538 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016539 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016540 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016541 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16542 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016543 if($Level eq "Source" and $ReportFormat eq "html")
16544 { # do not show library name in HTML report
16545 $DyLib = "";
16546 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016547 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016548 }
16549 }
16550 }
16551 if($ReportFormat eq "xml")
16552 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016553 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016554 {
16555 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016556 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016557 {
16558 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016559 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16560 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016561 }
16562 $REMOVED_INTERFACES .= " </library>\n";
16563 }
16564 $REMOVED_INTERFACES .= " </header>\n";
16565 }
16566 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16567 }
16568 else
16569 { # HTML
16570 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016571 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016572 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016573 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016574 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016575 my %NameSpaceSymbols = ();
16576 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016577 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016578 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016579 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016580 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016581 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16582 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016583 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016584 {
16585 $Removed_Number += 1;
16586 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016587 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016588 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016589 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016590 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016591 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016592 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016593 if($Signature) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016594 $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 +040016595 }
16596 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016597 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016598 }
16599 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016600 else
16601 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016602 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016603 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016604 }
16605 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016606 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016607 }
16608 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016609 }
16610 }
16611 $REMOVED_INTERFACES .= "<br/>\n";
16612 }
16613 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016614 if($REMOVED_INTERFACES)
16615 {
16616 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16617 if($JoinReport) {
16618 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16619 }
16620 $REMOVED_INTERFACES = $Anchor."<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016621 }
16622 }
16623 return $REMOVED_INTERFACES;
16624}
16625
16626sub getXmlParams($$)
16627{
16628 my ($Content, $Problem) = @_;
16629 return "" if(not $Content or not $Problem);
16630 my %XMLparams = ();
16631 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16632 {
16633 my $Macro = "\@".lc($Attr);
16634 if($Content=~/\Q$Macro\E/) {
16635 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16636 }
16637 }
16638 my @PString = ();
16639 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016640 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016641 }
16642 if(@PString) {
16643 return " ".join(" ", @PString);
16644 }
16645 else {
16646 return "";
16647 }
16648}
16649
16650sub addMarkup($)
16651{
16652 my $Content = $_[0];
16653 # auto-markup
16654 $Content=~s/\n[ ]*//; # spaces
16655 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16656 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016657 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016658 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16659 if($Content=~/\ANOTE:/)
16660 { # notes
16661 $Content=~s!(NOTE):!<b>$1</b>:!g;
16662 }
16663 else {
16664 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16665 }
16666 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16667 my @Keywords = (
16668 "void",
16669 "const",
16670 "static",
16671 "restrict",
16672 "volatile",
16673 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016674 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016675 );
16676 my $MKeys = join("|", @Keywords);
16677 foreach (@Keywords) {
16678 $MKeys .= "|non-".$_;
16679 }
16680 $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 +040016681
16682 # Markdown
16683 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16684 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016685 return $Content;
16686}
16687
16688sub applyMacroses($$$$)
16689{
16690 my ($Level, $Kind, $Content, $Problem) = @_;
16691 return "" if(not $Content or not $Problem);
16692 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16693 $Content = addMarkup($Content);
16694 # macros
16695 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16696 {
16697 my $Macro = "\@".lc($Attr);
16698 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016699 if(not defined $Value
16700 or $Value eq "") {
16701 next;
16702 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016703 if($Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016704 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016705 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
16706 $Value=~s/\s\w+(\)|,)/$1/g; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016707 $Value = black_name($Value);
16708 }
16709 elsif($Value=~/\s/) {
16710 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16711 }
16712 elsif($Value=~/\A\d+\Z/
16713 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16714 { # bits to bytes
16715 if($Value % $BYTE_SIZE)
16716 { # bits
16717 if($Value==1) {
16718 $Value = "<b>".$Value."</b> bit";
16719 }
16720 else {
16721 $Value = "<b>".$Value."</b> bits";
16722 }
16723 }
16724 else
16725 { # bytes
16726 $Value /= $BYTE_SIZE;
16727 if($Value==1) {
16728 $Value = "<b>".$Value."</b> byte";
16729 }
16730 else {
16731 $Value = "<b>".$Value."</b> bytes";
16732 }
16733 }
16734 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016735 else
16736 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016737 $Value = "<b>".htmlSpecChars($Value)."</b>";
16738 }
16739 $Content=~s/\Q$Macro\E/$Value/g;
16740 }
16741
16742 if($Content=~/(\A|[^\@\w])\@\w/)
16743 {
16744 if(not $IncompleteRules{$Level}{$Kind})
16745 { # only one warning
16746 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16747 $IncompleteRules{$Level}{$Kind} = 1;
16748 }
16749 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016750 return $Content;
16751}
16752
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016753sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016754{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016755 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016756 my $INTERFACE_PROBLEMS = "";
16757 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016758
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016759 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016760 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016761 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16762 if($SV and defined $CompatProblems{$Level}{$SN}) {
16763 next;
16764 }
16765 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016766 {
16767 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016768 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016769 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016770 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16771 my $DyLib = $Symbol_Library{1}{$Symbol};
16772 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016773 { # Symbol with Version
16774 $DyLib = $Symbol_Library{1}{$VSym};
16775 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016776 if(not $DyLib)
16777 { # const global data
16778 $DyLib = "";
16779 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016780 if($Level eq "Source" and $ReportFormat eq "html")
16781 { # do not show library name in HTML report
16782 $DyLib = "";
16783 }
16784 %{$SymbolChanges{$Symbol}{$Kind}} = %{$CompatProblems{$Level}{$Symbol}{$Kind}};
16785 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016786 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016787 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
16788 if($Severity ne $TargetSeverity) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016789 delete($SymbolChanges{$Symbol}{$Kind}{$Location});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016790 }
16791 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016792 if(not keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16793 {
16794 delete($SymbolChanges{$Symbol}{$Kind});
16795 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016796 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016797 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016798 }
16799 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016800 if(not keys(%{$SymbolChanges{$Symbol}})) {
16801 delete($SymbolChanges{$Symbol});
16802 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016803 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016804
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016805 if($ReportFormat eq "xml")
16806 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016807 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016808 {
16809 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016810 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016811 {
16812 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016813 foreach my $Symbol (sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%SymbolChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016814 {
16815 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
16816 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
16817 {
16818 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16819 {
16820 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016821 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016822
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016823 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16824 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16825 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16826 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16827 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
16828 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
16829 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16830 $INTERFACE_PROBLEMS .= " </problem>\n";
16831 }
16832 }
16833 $INTERFACE_PROBLEMS .= " </symbol>\n";
16834 }
16835 $INTERFACE_PROBLEMS .= " </library>\n";
16836 }
16837 $INTERFACE_PROBLEMS .= " </header>\n";
16838 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016839 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016840 }
16841 else
16842 { # HTML
16843 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016844 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016845 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016846 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016847 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016848 my (%NameSpaceSymbols, %NewSignature) = ();
16849 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016850 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016851 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016852 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016853 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016854 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016855 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 +040016856 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016857 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016858 my $Signature = get_Signature($Symbol, 1);
16859 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016860 my $ProblemNum = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016861 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016862 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016863 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016864 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016865 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016866 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016867 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016868 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016869 }
16870 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16871 {
16872 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016873 $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 +040016874 $ProblemNum += 1;
16875 $ProblemsNum += 1;
16876 }
16877 }
16878 }
16879 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016880 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016881 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016882 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016883 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016884 $INTERFACE_PROBLEMS .= highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016885 }
16886 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016887 $INTERFACE_PROBLEMS .= $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016888 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016889 $INTERFACE_PROBLEMS .= " ($ProblemNum)".$ContentSpanEnd."<br/>\n";
16890 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
16891 if($NewSignature{$Symbol})
16892 { # argument list changed to
16893 $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 +040016894 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016895 if($Symbol=~/\A(_Z|\?)/) {
16896 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
16897 }
16898 $INTERFACE_PROBLEMS .= "<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>$SYMBOL_REPORT</table><br/>\n";
16899 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016900 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016901 $INTERFACE_PROBLEMS=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016902 }
16903 }
16904 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016905 $INTERFACE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016906 }
16907 }
16908 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016909
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016910 if($INTERFACE_PROBLEMS)
16911 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016912 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
16913 my $Title = "Problems with Symbols, $TargetSeverity Severity";
16914 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016915 { # Safe Changes
16916 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016917 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016918 $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 +040016919 }
16920 }
16921 return $INTERFACE_PROBLEMS;
16922}
16923
16924sub get_Report_TypeProblems($$)
16925{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016926 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016927 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016928 my (%ReportMap, %TypeChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016929
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016930 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016931 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016932 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016933 {
16934 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
16935 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016936 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016937 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016938 my $TypeName = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016939 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016940 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016941
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016942 if($Severity eq "Safe"
16943 and $TargetSeverity ne "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016944 next;
16945 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016946
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016947 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$TypeName}{$Kind}{$Target})
16948 {
16949 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
16950 { # select a problem with the highest priority
16951 next;
16952 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016953 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016954
16955 $TypeChanges{$TypeName}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016956 }
16957 }
16958 }
16959 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016960
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016961 my %Kinds_Locations = ();
16962 foreach my $TypeName (keys(%TypeChanges))
16963 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016964 my %Kind_Target = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016965 foreach my $Kind (sort keys(%{$TypeChanges{$TypeName}}))
16966 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016967 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016968 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016969 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016970 if($Severity ne $TargetSeverity)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016971 { # other priority
16972 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16973 next;
16974 }
16975 $Kinds_Locations{$TypeName}{$Kind}{$Location} = 1;
16976 my $Target = $TypeChanges{$TypeName}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016977 if($Kind_Target{$Kind}{$Target})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016978 { # duplicate target
16979 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16980 next;
16981 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016982 $Kind_Target{$Kind}{$Target} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016983 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016984 $ReportMap{$HeaderName}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016985 }
16986 if(not keys(%{$TypeChanges{$TypeName}{$Kind}})) {
16987 delete($TypeChanges{$TypeName}{$Kind});
16988 }
16989 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016990 if(not keys(%{$TypeChanges{$TypeName}})) {
16991 delete($TypeChanges{$TypeName});
16992 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016993 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016994
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016995 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 +040016996 if($ReportFormat eq "xml")
16997 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016998 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016999 {
17000 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017001 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017002 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017003 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017004 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
17005 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017006 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017007 {
17008 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
17009 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
17010 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
17011 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
17012 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
17013 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
17014 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
17015 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
17016 $TYPE_PROBLEMS .= " </problem>\n";
17017 }
17018 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017019 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017020 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017021 $TYPE_PROBLEMS .= showVTables($TypeName);
17022 }
17023 $TYPE_PROBLEMS .= " </type>\n";
17024 }
17025 $TYPE_PROBLEMS .= " </header>\n";
17026 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017027 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017028 }
17029 else
17030 { # HTML
17031 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017032 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017033 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017034 my (%NameSpace_Type) = ();
17035 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017036 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017037 }
17038 foreach my $NameSpace (sort keys(%NameSpace_Type))
17039 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017040 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017041 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 +040017042 foreach my $TypeName (@SortedTypes)
17043 {
17044 my $ProblemNum = 1;
17045 my $TYPE_REPORT = "";
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017046
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017047 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
17048 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017049 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017050 {
17051 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
17052 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
17053 {
17054 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
17055 $TYPE_REPORT .= "<tr><th>$ProblemNum</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
17056 $ProblemNum += 1;
17057 $ProblemsNum += 1;
17058 }
17059 }
17060 }
17061 $ProblemNum -= 1;
17062 if($TYPE_REPORT)
17063 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017064 my $Affected = getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017065 my $ShowVTables = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017066 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017067 $ShowVTables = showVTables($TypeName);
17068 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017069
17070 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ".show_Type($TypeName, 1, 1)." ($ProblemNum)".$ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017071 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
17072 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
17073 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
17074 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017075 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017076 $TYPE_PROBLEMS=~s/\b\Q$NameSpace\E::(\w|\~)/$1/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017077 }
17078 }
17079 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017080 $TYPE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017081 }
17082 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017083
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017084 if($TYPE_PROBLEMS)
17085 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017086 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
17087 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017088 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017089 { # Safe Changes
17090 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017091 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017092 $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 +040017093 }
17094 }
17095 return $TYPE_PROBLEMS;
17096}
17097
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017098sub show_Type($$$)
17099{
17100 my ($Name, $Html, $LibVersion) = @_;
17101 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
17102 $TType = lc($TType);
17103 if($TType=~/struct|union|enum/) {
17104 $Name=~s/\A\Q$TType\E //g;
17105 }
17106 if($Html) {
17107 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
17108 }
17109 else {
17110 $Name = $TType." ".$Name;
17111 }
17112 return $Name;
17113}
17114
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017115sub get_Anchor($$$)
17116{
17117 my ($Kind, $Level, $Severity) = @_;
17118 if($JoinReport)
17119 {
17120 if($Severity eq "Safe") {
17121 return "Other_".$Level."_Changes_In_".$Kind."s";
17122 }
17123 else {
17124 return $Kind."_".$Level."_Problems_".$Severity;
17125 }
17126 }
17127 else
17128 {
17129 if($Severity eq "Safe") {
17130 return "Other_Changes_In_".$Kind."s";
17131 }
17132 else {
17133 return $Kind."_Problems_".$Severity;
17134 }
17135 }
17136}
17137
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017138sub showVTables($)
17139{
17140 my $TypeName = $_[0];
17141 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017142 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017143 if(defined $Type1{"VTable"}
17144 and keys(%{$Type1{"VTable"}}))
17145 {
17146 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017147 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017148 if(defined $Type2{"VTable"}
17149 and keys(%{$Type2{"VTable"}}))
17150 {
17151 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
17152 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017153 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017154 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017155 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
17156 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017157 }
17158 my $VTABLES = "";
17159 if($ReportFormat eq "xml")
17160 { # XML
17161 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017162 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017163 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017164 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017165 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
17166 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017167 $VTABLES .= " </entry>\n";
17168 }
17169 $VTABLES .= " </vtable>\n\n";
17170 }
17171 else
17172 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017173 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017174 $VTABLES .= "<tr><th width='2%'>Offset</th>";
17175 $VTABLES .= "<th width='45%'>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
17176 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017177 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017178 {
17179 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017180 if($Entries{$Index}{"E1"} ne $Entries{$Index}{"E2"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017181 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017182 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017183 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017184 $Color1 = " class='failed'";
17185 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017186 }
17187 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017188 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017189 }
17190 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017191 $VTABLES .= "<tr><th>".$Index."</th>\n";
17192 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
17193 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017194 }
17195 $VTABLES .= "</table><br/>\n";
17196 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017197 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017198 }
17199 return $VTABLES;
17200 }
17201 }
17202 return "";
17203}
17204
17205sub simpleVEntry($)
17206{
17207 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017208 if(not defined $VEntry
17209 or $VEntry eq "") {
17210 return "";
17211 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017212 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
17213 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
17214 if($VEntry=~/\A_ZThn.+\Z/) {
17215 $VEntry = "non-virtual thunk";
17216 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017217 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017218 # support for old GCC versions
17219 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
17220 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
17221 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017222 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
17223 return $VEntry;
17224}
17225
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017226sub adjustParamPos($$$)
17227{
17228 my ($Pos, $Symbol, $LibVersion) = @_;
17229 if(defined $CompleteSignature{$LibVersion}{$Symbol})
17230 {
17231 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Static"}
17232 and $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
17233 {
17234 return $Pos-1;
17235 }
17236
17237 return $Pos;
17238 }
17239
17240 return undef;
17241}
17242
17243sub getParamPos($$$)
17244{
17245 my ($Name, $Symbol, $LibVersion) = @_;
17246
17247 if(defined $CompleteSignature{$LibVersion}{$Symbol}
17248 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"})
17249 {
17250 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17251 foreach (keys(%{$Info->{"Param"}}))
17252 {
17253 if($Info->{"Param"}{$_}{"name"} eq $Name)
17254 {
17255 return $_;
17256 }
17257 }
17258 }
17259
17260 return undef;
17261}
17262
17263sub getParamName($)
17264{
17265 my $Loc = $_[0];
17266 $Loc=~s/\->.*//g;
17267 return $Loc;
17268}
17269
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017270sub getAffectedSymbols($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017271{
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017272 my ($Level, $Target_TypeName, $Kinds_Locations, $Syms) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017273 my $LIMIT = 1000;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017274
17275 if(defined $AffectLimit)
17276 {
17277 $LIMIT = $AffectLimit;
17278 }
17279 else
17280 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017281 if($#{$Syms}>=1999)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017282 { # reduce size of the report
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017283 $AffectLimit = 10;
17284
17285 printMsg("WARNING", "reducing limit of affected symbols shown in the report to $AffectLimit");
17286 $LIMIT = $AffectLimit;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017287 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017288 }
17289 my %SProblems = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017290 LOOP: foreach my $Symbol (@{$Syms})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017291 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017292 if(index($Symbol, "_Z")==0
17293 and $Symbol=~/(C2|D2|D0)[EI]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017294 { # duplicated problems for C2 constructors, D2 and D0 destructors
17295 next;
17296 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017297
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017298 my ($MinPath_Length, $ProblemLocation_Last) = (-1, "");
17299 my $Severity_Max = 0;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017300
17301 foreach my $Kind (keys(%{$Kinds_Locations}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017302 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017303 if(not defined $CompatProblems{$Level}{$Symbol}
17304 or not defined $CompatProblems{$Level}{$Symbol}{$Kind}) {
17305 next;
17306 }
17307
17308 foreach my $Location (keys(%{$Kinds_Locations->{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017309 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017310 if(keys(%SProblems)>$LIMIT) {
17311 last LOOP;
17312 }
17313
17314 if(not defined $CompatProblems{$Level}{$Symbol}{$Kind}{$Location}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017315 next;
17316 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017317
17318 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17319 if($Level eq "Source")
17320 { # remove symbol version
17321 $Symbol=$SN;
17322 }
17323
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017324 if($SV and defined $CompatProblems{$Level}{$SN}
17325 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Location})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017326 { # duplicated problems for versioned symbols
17327 next;
17328 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017329
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017330 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017331 if($Type_Name ne $Target_TypeName) {
17332 next;
17333 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017334
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017335 my $PName = getParamName($Location);
17336 my $PPos = adjustParamPos(getParamPos($PName, $Symbol, 1), $Symbol, 1);
17337
17338 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017339 my $Path_Length = 0;
17340 my $ProblemLocation = $Location;
17341 if($Type_Name) {
17342 $ProblemLocation=~s/->\Q$Type_Name\E\Z//g;
17343 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017344 while($ProblemLocation=~/\-\>/g) {
17345 $Path_Length += 1;
17346 }
17347 if($MinPath_Length==-1 or ($Path_Length<=$MinPath_Length and $Severity_Val{$Severity}>$Severity_Max)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017348 or (cmpLocations($ProblemLocation, $ProblemLocation_Last) and $Severity_Val{$Severity}==$Severity_Max))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017349 {
17350 $MinPath_Length = $Path_Length;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017351 $Severity_Max = $Severity_Val{$Severity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017352 $ProblemLocation_Last = $ProblemLocation;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017353 %{$SProblems{$Symbol}} = (
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017354 "Descr"=>getAffectDesc($Level, $Symbol, $Kind, $Location),
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017355 "Severity_Max"=>$Severity_Max,
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017356 "Signature"=>get_Signature($Symbol, 1),
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017357 "Position"=>$PPos,
17358 "Param_Name"=>$PName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017359 "Location"=>$Location
17360 );
17361 }
17362 }
17363 }
17364 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017365 my @Symbols = keys(%SProblems);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017366 @Symbols = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} @Symbols;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017367 @Symbols = sort {$SProblems{$b}{"Severity_Max"}<=>$SProblems{$a}{"Severity_Max"}} @Symbols;
17368 if($#Symbols+1>$LIMIT)
17369 { # remove last element
17370 pop(@Symbols);
17371 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017372 my $Affected = "";
17373 if($ReportFormat eq "xml")
17374 { # XML
17375 $Affected .= " <affected>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017376 foreach my $Symbol (@Symbols)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017377 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017378 my $Param_Name = $SProblems{$Symbol}{"Param_Name"};
17379 my $Description = $SProblems{$Symbol}{"Descr"};
17380 my $Location = $SProblems{$Symbol}{"Location"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017381 my $Target = "";
17382 if($Param_Name) {
17383 $Target = " affected=\"param\" param_name=\"$Param_Name\"";
17384 }
17385 elsif($Location=~/\Aretval(\-|\Z)/i) {
17386 $Target = " affected=\"retval\"";
17387 }
17388 elsif($Location=~/\Athis(\-|\Z)/i) {
17389 $Target = " affected=\"this\"";
17390 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017391 $Affected .= " <symbol$Target name=\"$Symbol\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017392 $Affected .= " <comment>".xmlSpecChars($Description)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017393 $Affected .= " </symbol>\n";
17394 }
17395 $Affected .= " </affected>\n";
17396 }
17397 else
17398 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017399 foreach my $Symbol (@Symbols)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017400 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017401 my $Description = $SProblems{$Symbol}{"Descr"};
17402 my $Signature = $SProblems{$Symbol}{"Signature"};
17403 my $Pos = $SProblems{$Symbol}{"Position"};
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017404 $Affected .= "<span class='iname_a'>".highLight_Signature_PPos_Italic($Signature, $Pos, 1, 0, 0)."</span><br/><div class='affect'>".htmlSpecChars($Description)."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017405 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017406 if(keys(%SProblems)>$LIMIT) {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017407 $Affected .= " ...<br/>"; # and others ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017408 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017409 $Affected = "<div class='affected'>".$Affected."</div>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017410 if($Affected)
17411 {
17412 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017413 $Affected = $ContentSpanStart_Affected."[+] affected symbols (".(keys(%SProblems)>$LIMIT?">".$LIMIT:keys(%SProblems)).")".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017414 }
17415 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017416
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017417 return $Affected;
17418}
17419
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017420sub cmpLocations($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017421{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017422 my ($L1, $L2) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017423 if($L2=~/\A(retval|this)\b/
17424 and $L1!~/\A(retval|this)\b/)
17425 {
17426 if($L1!~/\-\>/) {
17427 return 1;
17428 }
17429 elsif($L2=~/\-\>/) {
17430 return 1;
17431 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017432 }
17433 return 0;
17434}
17435
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017436sub getAffectDesc($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017437{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017438 my ($Level, $Symbol, $Kind, $Location) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017439
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017440 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017441
17442 my $Location_I = $Location;
17443 $Location=~s/\A(.*)\-\>(.+?)\Z/$1/; # without the latest affected field
17444
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017445 my @Sentence = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017446
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017447 if($Kind eq "Overridden_Virtual_Method"
17448 or $Kind eq "Overridden_Virtual_Method_B") {
17449 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17450 }
17451 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17452 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017453 my %SymInfo = %{$CompleteSignature{1}{$Symbol}};
17454
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017455 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17456 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017457 my $METHOD_TYPE = $SymInfo{"Constructor"}?"constructor":"method";
17458 my $ClassName = $TypeInfo{1}{$SymInfo{"Class"}}{"Name"};
17459
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017460 if($ClassName eq $Problem{"Type_Name"}) {
17461 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17462 }
17463 else {
17464 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17465 }
17466 }
17467 else
17468 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017469 my $TypeID = undef;
17470
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017471 if($Location=~/retval/)
17472 { # return value
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017473 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017474 push(@Sentence, "Field \'".$Location."\' in return value");
17475 }
17476 else {
17477 push(@Sentence, "Return value");
17478 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017479
17480 $TypeID = $SymInfo{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017481 }
17482 elsif($Location=~/this/)
17483 { # "this" pointer
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017484 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017485 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17486 }
17487 else {
17488 push(@Sentence, "\'this\' pointer");
17489 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017490
17491 $TypeID = $SymInfo{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017492 }
17493 else
17494 { # parameters
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017495
17496 my $PName = getParamName($Location);
17497 my $PPos = getParamPos($PName, $Symbol, 1);
17498
17499 if(index($Location, "->")!=-1) {
17500 push(@Sentence, "Field \'".$Location."\' in ".showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017501 }
17502 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017503 push(@Sentence, showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017504 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017505 if($PName) {
17506 push(@Sentence, "\'".$PName."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017507 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017508
17509 $TypeID = $SymInfo{"Param"}{$PPos}{"type"};
17510 }
17511
17512 if($Location!~/this/)
17513 {
17514 if(my %PureType = get_PureType($TypeID, $TypeInfo{1}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017515 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017516 if($PureType{"Type"} eq "Pointer") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017517 push(@Sentence, "(pointer)");
17518 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017519 elsif($PureType{"Type"} eq "Ref") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017520 push(@Sentence, "(reference)");
17521 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017522 }
17523 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017524
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017525 if($Location eq "this") {
17526 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17527 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017528 else
17529 {
17530 my $Location_T = $Location;
17531 $Location_T=~s/\A\w+(\->|\Z)//; # location in type
17532
17533 my $TypeID_Problem = $TypeID;
17534 if($Location_T) {
17535 $TypeID_Problem = getFieldType($Location_T, $TypeID, 1);
17536 }
17537
17538 if($TypeInfo{1}{$TypeID_Problem}{"Name"} eq $Problem{"Type_Name"}) {
17539 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17540 }
17541 else {
17542 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17543 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017544 }
17545 }
17546 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017547 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017548 push(@Sentence, " This is a symbol from an external library that may use the \'$TargetLibraryName\' library and change the ABI after recompiling.");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017549 }
17550 return join(" ", @Sentence);
17551}
17552
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017553sub getFieldType($$$)
17554{
17555 my ($Location, $TypeId, $LibVersion) = @_;
17556
17557 my @Fields = split("->", $Location);
17558
17559 foreach my $Name (@Fields)
17560 {
17561 my %Info = get_BaseType($TypeId, $LibVersion);
17562
17563 foreach my $Pos (keys(%{$Info{"Memb"}}))
17564 {
17565 if($Info{"Memb"}{$Pos}{"name"} eq $Name)
17566 {
17567 $TypeId = $Info{"Memb"}{$Pos}{"type"};
17568 last;
17569 }
17570 }
17571 }
17572
17573 return $TypeId;
17574}
17575
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017576sub get_XmlSign($$)
17577{
17578 my ($Symbol, $LibVersion) = @_;
17579 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17580 my $Report = "";
17581 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17582 {
17583 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017584 my $Type = $Info->{"Param"}{$Pos}{"type"};
17585 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017586 foreach my $Typedef (keys(%ChangedTypedef))
17587 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017588 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17589 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17590 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017591 }
17592 $Report .= " <param pos=\"$Pos\">\n";
17593 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017594 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017595 $Report .= " </param>\n";
17596 }
17597 if(my $Return = $Info->{"Return"})
17598 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017599 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017600 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017601 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017602 $Report .= " </retval>\n";
17603 }
17604 return $Report;
17605}
17606
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017607sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017608{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017609 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017610 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017611 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017612 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017613 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17614 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017615 next;
17616 }
17617 $Report .= " <symbol name=\"$Symbol\">\n";
17618 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017619 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017620 {
17621 if(defined $CompleteSignature{1}{$Symbol}
17622 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17623 {
17624 $P1 = get_XmlSign($Symbol, 1);
17625 $S1 = get_Signature($Symbol, 1);
17626 }
17627 elsif($Symbol=~/\A(_Z|\?)/) {
17628 $S1 = $tr_name{$Symbol};
17629 }
17630 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017631 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017632 {
17633 if(defined $CompleteSignature{2}{$Symbol}
17634 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17635 {
17636 $P2 = get_XmlSign($Symbol, 2);
17637 $S2 = get_Signature($Symbol, 2);
17638 }
17639 elsif($Symbol=~/\A(_Z|\?)/) {
17640 $S2 = $tr_name{$Symbol};
17641 }
17642 }
17643 if($S1)
17644 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017645 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017646 $Report .= $P1;
17647 $Report .= " </old>\n";
17648 }
17649 if($S2 and $S2 ne $S1)
17650 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017651 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017652 $Report .= $P2;
17653 $Report .= " </new>\n";
17654 }
17655 $Report .= " </symbol>\n";
17656 }
17657 $Report .= "</symbols_info>\n";
17658 return $Report;
17659}
17660
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017661sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017662{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017663 my ($Level, $Report) = @_;
17664 if($ReportFormat eq "xml") {
17665 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017666 }
17667 if($StdOut)
17668 { # --stdout option
17669 print STDOUT $Report;
17670 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017671 else
17672 {
17673 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017674 mkpath(get_dirname($RPath));
17675
17676 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17677 print REPORT $Report;
17678 close(REPORT);
17679
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017680 if($Browse or $OpenReport)
17681 { # open in browser
17682 openReport($RPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017683 if($JoinReport or $DoubleReport)
17684 {
17685 if($Level eq "Binary")
17686 { # wait to open a browser
17687 sleep(1);
17688 }
17689 }
17690 }
17691 }
17692}
17693
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017694sub openReport($)
17695{
17696 my $Path = $_[0];
17697 my $Cmd = "";
17698 if($Browse)
17699 { # user-defined browser
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017700 $Cmd = $Browse." \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017701 }
17702 if(not $Cmd)
17703 { # default browser
17704 if($OSgroup eq "macos") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040017705 $Cmd = "open \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017706 }
17707 elsif($OSgroup eq "windows") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040017708 $Cmd = "start ".path_format($Path, $OSgroup);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017709 }
17710 else
17711 { # linux, freebsd, solaris
17712 my @Browsers = (
17713 "x-www-browser",
17714 "sensible-browser",
17715 "firefox",
17716 "opera",
17717 "xdg-open",
17718 "lynx",
17719 "links"
17720 );
17721 foreach my $Br (@Browsers)
17722 {
17723 if($Br = get_CmdPath($Br))
17724 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017725 $Cmd = $Br." \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017726 last;
17727 }
17728 }
17729 }
17730 }
17731 if($Cmd)
17732 {
17733 if($Debug) {
17734 printMsg("INFO", "running $Cmd");
17735 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040017736 if($OSgroup ne "windows"
17737 and $OSgroup ne "macos")
17738 {
17739 if($Cmd!~/lynx|links/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017740 $Cmd .= " >\"/dev/null\" 2>&1 &";
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040017741 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017742 }
17743 system($Cmd);
17744 }
17745 else {
17746 printMsg("ERROR", "cannot open report in browser");
17747 }
17748}
17749
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017750sub getReport($)
17751{
17752 my $Level = $_[0];
17753 if($ReportFormat eq "xml")
17754 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017755 if($Level eq "Join")
17756 {
17757 my $Report = "<reports>\n";
17758 $Report .= getReport("Binary");
17759 $Report .= getReport("Source");
17760 $Report .= "</reports>\n";
17761 return $Report;
17762 }
17763 else
17764 {
17765 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17766 my ($Summary, $MetaData) = get_Summary($Level);
17767 $Report .= $Summary."\n";
17768 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17769 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17770 $Report .= get_Report_SymbolsInfo($Level);
17771 $Report .= "</report>\n";
17772 return $Report;
17773 }
17774 }
17775 else
17776 { # HTML
17777 my $CssStyles = readModule("Styles", "Report.css");
17778 my $JScripts = readModule("Scripts", "Sections.js");
17779 if($Level eq "Join")
17780 {
17781 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17782 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040017783 my $Title = $TargetLibraryFName.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
17784 my $Keywords = $TargetLibraryFName.", compatibility, API, report";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017785 my $Description = "Compatibility report for the $TargetLibraryFName $TargetComponent between ".$Descriptor{1}{"Version"}." and ".$Descriptor{2}{"Version"}." versions";
17786 my ($BSummary, $BMetaData) = get_Summary("Binary");
17787 my ($SSummary, $SMetaData) = get_Summary("Source");
17788 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>";
17789 $Report .= get_Report_Header("Join")."
17790 <br/><div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017791 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17792 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017793 </div>";
17794 $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>";
17795 $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 +040017796 $Report .= getReportFooter($TargetLibraryFName, not $JoinReport);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017797 $Report .= "\n<div style='height:999px;'></div>\n</body></html>";
17798 return $Report;
17799 }
17800 else
17801 {
17802 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040017803 my $Title = $TargetLibraryFName.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17804 my $Keywords = $TargetLibraryFName.", ".lc($Level)." compatibility, API, report";
17805 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 +040017806 if($Level eq "Binary")
17807 {
17808 if(getArch(1) eq getArch(2)
17809 and getArch(1) ne "unknown") {
17810 $Description .= " on ".showArch(getArch(1));
17811 }
17812 }
17813 my $Report = "<!-\- $MetaData -\->\n".composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."\n<body>\n<div><a name='Top'></a>\n";
17814 $Report .= get_Report_Header($Level)."\n".$Summary."\n";
17815 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17816 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17817 $Report .= get_SourceInfo();
17818 $Report .= "</div>\n<br/><br/><br/><hr/>\n";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017819 $Report .= getReportFooter($TargetLibraryFName, not $JoinReport);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017820 $Report .= "\n<div style='height:999px;'></div>\n</body></html>";
17821 return $Report;
17822 }
17823 }
17824}
17825
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017826sub getLegend()
17827{
17828 return "<br/>
17829<table class='summary'>
17830<tr>
17831 <td class='new'>added</td>
17832 <td class='passed'>compatible</td>
17833</tr>
17834<tr>
17835 <td class='warning'>warning</td>
17836 <td class='failed'>incompatible</td>
17837</tr></table>\n";
17838}
17839
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017840sub createReport()
17841{
17842 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017843 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017844 writeReport("Join", getReport("Join"));
17845 }
17846 elsif($DoubleReport)
17847 { # default
17848 writeReport("Binary", getReport("Binary"));
17849 writeReport("Source", getReport("Source"));
17850 }
17851 elsif($BinaryOnly)
17852 { # --binary
17853 writeReport("Binary", getReport("Binary"));
17854 }
17855 elsif($SourceOnly)
17856 { # --source
17857 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017858 }
17859}
17860
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017861sub getReportFooter($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017862{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017863 my ($LibName, $Wide) = @_;
17864 my $FooterStyle = $Wide?"width:99%":"width:97%;padding-top:3px";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017865 my $Footer = "<div style='$FooterStyle;font-size:11px;' align='right'><i>Generated on ".(localtime time); # report date
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017866 $Footer .= " for <span style='font-weight:bold'>$LibName</span>"; # tested library/system name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017867 $Footer .= " by <a href='".$HomePage{"Wiki"}."'>ABI Compliance Checker</a>"; # tool name
17868 my $ToolSummary = "<br/>A tool for checking backward compatibility of a C/C++ library API&#160;&#160;";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017869 $Footer .= " $TOOL_VERSION &#160;$ToolSummary</i></div>"; # tool version
17870 return $Footer;
17871}
17872
17873sub get_Report_Problems($$)
17874{
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017875 my ($Severity, $Level) = @_;
17876 my $Report = get_Report_TypeProblems($Severity, $Level);
17877 if(my $SProblems = get_Report_SymbolProblems($Severity, $Level)) {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017878 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017879 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017880 if($Severity eq "Low")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017881 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017882 $Report .= get_Report_ChangedConstants("Low", $Level);
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +040017883 if($ReportFormat eq "html")
17884 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017885 if($CheckImpl and $Level eq "Binary") {
17886 $Report .= get_Report_Impl();
17887 }
17888 }
17889 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017890 if($Severity eq "Safe")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017891 {
17892 $Report .= get_Report_ChangedConstants("Safe", $Level);
17893 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017894 if($ReportFormat eq "html")
17895 {
17896 if($Report)
17897 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017898 if($JoinReport)
17899 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017900 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017901 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
17902 }
17903 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017904 $Report = "<a name=\'".$Severity."_Risk_".$Level."_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017905 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017906 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017907 else
17908 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017909 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017910 $Report = "<a name=\'Other_Changes\'></a>".$Report;
17911 }
17912 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017913 $Report = "<a name=\'".$Severity."_Risk_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017914 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017915 }
17916 }
17917 }
17918 return $Report;
17919}
17920
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017921sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017922{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017923 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
17924 return "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
17925 <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
17926 <head>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017927 <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
17928 <meta name=\"keywords\" content=\"$Keywords\" />
17929 <meta name=\"description\" content=\"$Description\" />
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017930 <title>
17931 $Title
17932 </title>
17933 <style type=\"text/css\">
17934 $Styles
17935 </style>
17936 <script type=\"text/javascript\" language=\"JavaScript\">
17937 <!--
17938 $Scripts
17939 -->
17940 </script>
17941 </head>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017942}
17943
17944sub insertIDs($)
17945{
17946 my $Text = $_[0];
17947 while($Text=~/CONTENT_ID/)
17948 {
17949 if(int($Content_Counter)%2) {
17950 $ContentID -= 1;
17951 }
17952 $Text=~s/CONTENT_ID/c_$ContentID/;
17953 $ContentID += 1;
17954 $Content_Counter += 1;
17955 }
17956 return $Text;
17957}
17958
17959sub checkPreprocessedUnit($)
17960{
17961 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017962 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017963 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017964 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017965
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017966 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017967 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017968 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017969 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017970 chomp($Line);
17971 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017972 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017973 $CurHeader = path_format($1, $OSgroup);
17974 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017975 $CurClass = "";
17976
17977 if(index($CurHeader, $TMP_DIR)==0) {
17978 next;
17979 }
17980
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017981 if(substr($CurHeaderName, 0, 1) eq "<")
17982 { # <built-in>, <command-line>, etc.
17983 $CurHeaderName = "";
17984 $CurHeader = "";
17985 }
17986
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017987 if($ExtraInfo)
17988 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017989 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017990 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
17991 }
17992 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017993 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017994 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017995 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017996 if($CurHeaderName)
17997 {
17998 if(not $Include_Neighbors{$Version}{$CurHeaderName}
17999 and not $Registered_Headers{$Version}{$CurHeader})
18000 { # not a target
18001 next;
18002 }
18003 if(not is_target_header($CurHeaderName, 1)
18004 and not is_target_header($CurHeaderName, 2))
18005 { # user-defined header
18006 next;
18007 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018008 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018009 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018010
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018011 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018012 {
18013 my ($Name, $Value) = ($1, $2);
18014 if(not $Constants{$Version}{$Name}{"Access"})
18015 {
18016 $Constants{$Version}{$Name}{"Access"} = "public";
18017 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018018 if($CurHeaderName) {
18019 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
18020 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018021 }
18022 }
18023 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
18024 $Constants{$Version}{$1}{"Access"} = "private";
18025 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018026 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018027 else
18028 {
18029 if(defined $ExtraDump)
18030 {
18031 if($Line=~/(\w+)\s*\(/)
18032 { # functions
18033 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
18034 }
18035 #elsif($Line=~/(\w+)\s*;/)
18036 #{ # data
18037 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
18038 #}
18039 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
18040 $CurClass = $2;
18041 }
18042 }
18043 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018044 }
18045 close(PREPROC);
18046 foreach my $Constant (keys(%{$Constants{$Version}}))
18047 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018048 if($Constants{$Version}{$Constant}{"Access"} eq "private")
18049 {
18050 delete($Constants{$Version}{$Constant});
18051 next;
18052 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040018053 if(not $ExtraDump and ($Constant=~/_h\Z/i
18054 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018055 { # skip
18056 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018057 }
18058 else {
18059 delete($Constants{$Version}{$Constant}{"Access"});
18060 }
18061 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018062 if($Debug)
18063 {
18064 mkpath($DEBUG_PATH{$Version});
18065 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
18066 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018067}
18068
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018069sub uncoverConstant($$)
18070{
18071 my ($LibVersion, $Constant) = @_;
18072 return "" if(not $LibVersion or not $Constant);
18073 return $Constant if(isCyclical(\@RecurConstant, $Constant));
18074 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
18075 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
18076 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018077
18078 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018079 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018080 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
18081 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018082 {
18083 push(@RecurConstant, $Constant);
18084 my $Uncovered = uncoverConstant($LibVersion, $Value);
18085 if($Uncovered ne "") {
18086 $Value = $Uncovered;
18087 }
18088 pop(@RecurConstant);
18089 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018090
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018091 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018092 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018093 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
18094 }
18095 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
18096}
18097
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018098sub simpleConstant($$)
18099{
18100 my ($LibVersion, $Value) = @_;
18101 if($Value=~/\W/)
18102 {
18103 my $Value_Copy = $Value;
18104 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
18105 {
18106 my $Word = $1;
18107 if($Value!~/$Word\s*\(/)
18108 {
18109 my $Val = uncoverConstant($LibVersion, $Word);
18110 if($Val ne "")
18111 {
18112 $Value=~s/\b$Word\b/$Val/g;
18113 }
18114 }
18115 }
18116 }
18117 return $Value;
18118}
18119
18120sub computeValue($)
18121{
18122 my $Value = $_[0];
18123
18124 if($Value=~/\A\((-?[\d]+)\)\Z/) {
18125 return $1;
18126 }
18127
18128 if($Value=~/\A[\d\-\+()]+\Z/) {
18129 return eval($Value);
18130 }
18131
18132 return $Value;
18133}
18134
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018135my %IgnoreConstant = map {$_=>1} (
18136 "VERSION",
18137 "VERSIONCODE",
18138 "VERNUM",
18139 "VERS_INFO",
18140 "PATCHLEVEL",
18141 "INSTALLPREFIX",
18142 "VBUILD",
18143 "VPATCH",
18144 "VMINOR",
18145 "BUILD_STRING",
18146 "BUILD_TIME",
18147 "PACKAGE_STRING",
18148 "PRODUCTION",
18149 "CONFIGURE_COMMAND",
18150 "INSTALLDIR",
18151 "BINDIR",
18152 "CONFIG_FILE_PATH",
18153 "DATADIR",
18154 "EXTENSION_DIR",
18155 "INCLUDE_PATH",
18156 "LIBDIR",
18157 "LOCALSTATEDIR",
18158 "SBINDIR",
18159 "SYSCONFDIR",
18160 "RELEASE",
18161 "SOURCE_ID",
18162 "SUBMINOR",
18163 "MINOR",
18164 "MINNOR",
18165 "MINORVERSION",
18166 "MAJOR",
18167 "MAJORVERSION",
18168 "MICRO",
18169 "MICROVERSION",
18170 "BINARY_AGE",
18171 "INTERFACE_AGE",
18172 "CORE_ABI",
18173 "PATCH",
18174 "COPYRIGHT",
18175 "TIMESTAMP",
18176 "REVISION",
18177 "PACKAGE_TAG",
18178 "PACKAGEDATE",
18179 "NUMVERSION",
18180 "Release",
18181 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018182);
18183
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018184sub constantFilter($$$)
18185{
18186 my ($Name, $Value, $Level) = @_;
18187
18188 if($Level eq "Binary")
18189 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018190 if($Name=~/_t\Z/)
18191 { # __malloc_ptr_t
18192 return 1;
18193 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018194 foreach (keys(%IgnoreConstant))
18195 {
18196 if($Name=~/(\A|_)$_(_|\Z)/)
18197 { # version
18198 return 1;
18199 }
18200 if(/\A[A-Z].*[a-z]\Z/)
18201 {
18202 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
18203 { # version
18204 return 1;
18205 }
18206 }
18207 }
18208 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
18209 { # version
18210 return 1;
18211 }
18212 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
18213 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
18214 return 1;
18215 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018216
18217 if($Value=~/\A["'].*['"]/i)
18218 { # string
18219 return 0;
18220 }
18221
18222 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
18223 { # static int gcry_pth_init
18224 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018225 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018226 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018227 return 1;
18228 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018229 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018230 { # foo(p)
18231 return 1;
18232 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018233 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018234 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018235 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018236 return 1;
18237 }
18238 }
18239
18240 return 0;
18241}
18242
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018243sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018244{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018245 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018246 foreach my $Constant (keys(%{$Constants{1}}))
18247 {
18248 if($SkipConstants{1}{$Constant})
18249 { # skipped by the user
18250 next;
18251 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018252
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018253 if(my $Header = $Constants{1}{$Constant}{"Header"})
18254 {
18255 if(not is_target_header($Header, 1)
18256 and not is_target_header($Header, 2))
18257 { # user-defined header
18258 next;
18259 }
18260 }
18261 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018262 next;
18263 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018264
18265 my $Old_Value = uncoverConstant(1, $Constant);
18266
18267 if(constantFilter($Constant, $Old_Value, $Level))
18268 { # separate binary and source problems
18269 next;
18270 }
18271
18272 if(not defined $Constants{2}{$Constant}{"Value"})
18273 { # removed
18274 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
18275 "Target"=>$Constant,
18276 "Old_Value"=>$Old_Value );
18277 next;
18278 }
18279
18280 if($Constants{2}{$Constant}{"Value"} eq "")
18281 { # empty value
18282 # TODO: implement a rule
18283 next;
18284 }
18285
18286 my $New_Value = uncoverConstant(2, $Constant);
18287
18288 my $Old_Value_Pure = $Old_Value;
18289 my $New_Value_Pure = $New_Value;
18290
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018291 $Old_Value_Pure=~s/(\W)\s+/$1/g;
18292 $Old_Value_Pure=~s/\s+(\W)/$1/g;
18293 $New_Value_Pure=~s/(\W)\s+/$1/g;
18294 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018295
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018296 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018297
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018298 if($New_Value_Pure ne $Old_Value_Pure)
18299 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018300 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
18301 { # complex values
18302 next;
18303 }
18304 if(computeValue($Old_Value) eq computeValue($New_Value))
18305 { # expressions
18306 next;
18307 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018308 if(convert_integer($Old_Value) eq convert_integer($New_Value))
18309 { # 0x0001 and 0x1, 0x1 and 1 equal constants
18310 next;
18311 }
18312 if($Old_Value eq "0" and $New_Value eq "NULL")
18313 { # 0 => NULL
18314 next;
18315 }
18316 if($Old_Value eq "NULL" and $New_Value eq "0")
18317 { # NULL => 0
18318 next;
18319 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018320 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018321 "Target"=>$Constant,
18322 "Old_Value"=>$Old_Value,
18323 "New_Value"=>$New_Value );
18324 }
18325 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018326
18327 foreach my $Constant (keys(%{$Constants{2}}))
18328 {
18329 if(not defined $Constants{1}{$Constant}{"Value"})
18330 {
18331 if($SkipConstants{2}{$Constant})
18332 { # skipped by the user
18333 next;
18334 }
18335
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018336 if(my $Header = $Constants{2}{$Constant}{"Header"})
18337 {
18338 if(not is_target_header($Header, 1)
18339 and not is_target_header($Header, 2))
18340 { # user-defined header
18341 next;
18342 }
18343 }
18344 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018345 next;
18346 }
18347
18348 my $New_Value = uncoverConstant(2, $Constant);
18349 if(not defined $New_Value or $New_Value eq "") {
18350 next;
18351 }
18352
18353 if(constantFilter($Constant, $New_Value, $Level))
18354 { # separate binary and source problems
18355 next;
18356 }
18357
18358 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
18359 "Target"=>$Constant,
18360 "New_Value"=>$New_Value );
18361 }
18362 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018363}
18364
18365sub convert_integer($)
18366{
18367 my $Value = $_[0];
18368 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018369 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018370 return hex($Value);
18371 }
18372 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018373 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018374 return oct($Value);
18375 }
18376 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018377 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018378 return oct($Value);
18379 }
18380 else {
18381 return $Value;
18382 }
18383}
18384
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018385sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018386{
18387 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018388 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018389 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018390 {
18391 if($LibVersion==1)
18392 {
18393 printMsg("WARNING", "checking headers only");
18394 $CheckHeadersOnly = 1;
18395 }
18396 else {
18397 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
18398 }
18399 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018400
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018401 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018402 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018403 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018404
18405 if($CheckUndefined)
18406 {
18407 my %UndefinedLibs = ();
18408
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018409 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
18410
18411 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018412 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018413 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018414 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018415 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018416 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018417 if($Symbol_Library{$LibVersion}{$Symbol}
18418 or $DepSymbol_Library{$LibVersion}{$Symbol})
18419 { # exported by target library
18420 next;
18421 }
18422 if(index($Symbol, '@')!=-1)
18423 { # exported default symbol version (@@)
18424 $Symbol=~s/\@/\@\@/;
18425 if($Symbol_Library{$LibVersion}{$Symbol}
18426 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
18427 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018428 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018429 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018430 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
18431 $UndefinedLibs{$Path} = 1;
18432 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018433 }
18434 }
18435 }
18436 if($ExtraInfo)
18437 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018438 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018439 {
18440 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018441 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018442 foreach (@Paths)
18443 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018444 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018445 my ($Dir, $Name) = separate_path($_);
18446
18447 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018448 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018449 }
18450
18451 $Name = parse_libname($Name, "name", $OStarget);
18452 $Name=~s/\Alib//;
18453
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018454 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018455 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018456
18457 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
18458 {
18459 $LibString = " -L".esc($Dir).$LibString;
18460 }
18461
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018462 writeFile($ExtraInfo."/libs-string", $LibString);
18463 }
18464 }
18465 }
18466
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018467 if($ExtraInfo) {
18468 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
18469 }
18470
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018471 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018472 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018473 if($#LibPaths!=-1)
18474 {
18475 if(not keys(%{$Symbol_Library{$LibVersion}}))
18476 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040018477 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018478 printMsg("WARNING", "checking headers only");
18479 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018480 }
18481 }
18482 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018483
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018484 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018485 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018486}
18487
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018488my %Prefix_Lib_Map=(
18489 # symbols for autodetecting library dependencies (by prefix)
18490 "pthread_" => ["libpthread"],
18491 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
18492 "cairo_" => ["libcairo"],
18493 "gtk_" => ["libgtk-x11-2.0"],
18494 "atk_" => ["libatk-1.0"],
18495 "gdk_" => ["libgdk-x11-2.0"],
18496 "gl" => ["libGL"],
18497 "glu" => ["libGLU"],
18498 "popt" => ["libpopt"],
18499 "Py" => ["libpython"],
18500 "jpeg_" => ["libjpeg"],
18501 "BZ2_" => ["libbz2"],
18502 "Fc" => ["libfontconfig"],
18503 "Xft" => ["libXft"],
18504 "SSL_" => ["libssl"],
18505 "sem_" => ["libpthread"],
18506 "snd_" => ["libasound"],
18507 "art_" => ["libart_lgpl_2"],
18508 "dbus_g" => ["libdbus-glib-1"],
18509 "GOMP_" => ["libgomp"],
18510 "omp_" => ["libgomp"],
18511 "cms" => ["liblcms"]
18512);
18513
18514my %Pattern_Lib_Map=(
18515 "SL[a-z]" => ["libslang"]
18516);
18517
18518my %Symbol_Lib_Map=(
18519 # symbols for autodetecting library dependencies (by name)
18520 "pow" => "libm",
18521 "fmod" => "libm",
18522 "sin" => "libm",
18523 "floor" => "libm",
18524 "cos" => "libm",
18525 "dlopen" => "libdl",
18526 "deflate" => "libz",
18527 "inflate" => "libz",
18528 "move_panel" => "libpanel",
18529 "XOpenDisplay" => "libX11",
18530 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018531 "clock_gettime" => "librt",
18532 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018533);
18534
18535sub find_SymbolLibs($$)
18536{
18537 my ($LibVersion, $Symbol) = @_;
18538
18539 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
18540 { # debug symbols
18541 return ();
18542 }
18543
18544 my %Paths = ();
18545
18546 if(my $LibName = $Symbol_Lib_Map{$Symbol})
18547 {
18548 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18549 $Paths{$Path} = 1;
18550 }
18551 }
18552
18553 if(my $SymbolPrefix = getPrefix($Symbol))
18554 {
18555 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
18556 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
18557 }
18558
18559 if(not keys(%Paths))
18560 {
18561 if(defined $Prefix_Lib_Map{$SymbolPrefix})
18562 {
18563 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
18564 {
18565 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18566 $Paths{$Path} = 1;
18567 }
18568 }
18569 }
18570 }
18571
18572 if(not keys(%Paths))
18573 {
18574 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
18575 {
18576 if($Symbol=~/\A$Prefix/)
18577 {
18578 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
18579 {
18580 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18581 $Paths{$Path} = 1;
18582 }
18583 }
18584 }
18585 }
18586 }
18587
18588 if(not keys(%Paths))
18589 {
18590 if($SymbolPrefix)
18591 { # try to find a library by symbol prefix
18592 if($SymbolPrefix eq "inotify" and
18593 index($Symbol, "\@GLIBC")!=-1)
18594 {
18595 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
18596 $Paths{$Path} = 1;
18597 }
18598 }
18599 else
18600 {
18601 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
18602 $Paths{$Path} = 1;
18603 }
18604 }
18605 }
18606 }
18607
18608 if(my @Paths = keys(%Paths)) {
18609 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
18610 }
18611 }
18612 return keys(%Paths);
18613}
18614
18615sub get_LibPath_Prefix($$)
18616{
18617 my ($LibVersion, $Prefix) = @_;
18618
18619 $Prefix = lc($Prefix);
18620 $Prefix=~s/[_]+\Z//g;
18621
18622 foreach ("-2", "2", "-1", "1", "")
18623 { # libgnome-2.so
18624 # libxml2.so
18625 # libdbus-1.so
18626 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
18627 return $Path;
18628 }
18629 }
18630 return "";
18631}
18632
18633sub getPrefix($)
18634{
18635 my $Str = $_[0];
18636 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
18637 { # XmuValidArea: Xmu
18638 return $1;
18639 }
18640 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
18641 { # snfReadFont: snf
18642 return $1;
18643 }
18644 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
18645 { # XRRTimes: XRR
18646 return $1;
18647 }
18648 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
18649 { # H5HF_delete: H5
18650 return $1;
18651 }
18652 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
18653 { # alarm_event_add: alarm_
18654 return $1;
18655 }
18656 elsif($Str=~/\A(([a-z])\2{1,})/i)
18657 { # ffopen
18658 return $1;
18659 }
18660 return "";
18661}
18662
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018663sub getSymbolSize($$)
18664{ # size from the shared library
18665 my ($Symbol, $LibVersion) = @_;
18666 return 0 if(not $Symbol);
18667 if(defined $Symbol_Library{$LibVersion}{$Symbol}
18668 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
18669 {
18670 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
18671 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
18672 {
18673 if($Size<0) {
18674 return -$Size;
18675 }
18676 }
18677 }
18678 return 0;
18679}
18680
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018681sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018682{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
18683 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018684 my ($Name, $Type) = @_;
18685
18686 # single
18687 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018688 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018689 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018690 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018691 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018692
18693 # double
18694 if($Name=~/$DEFAULT_STD_PARMS/)
18695 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018696 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018697 {
18698 my ($ShortName, $FuncParams) = split_Signature($Name);
18699
18700 foreach my $FParam (separate_Params($FuncParams, 0, 0))
18701 {
18702 if(index($FParam, "<")!=-1)
18703 {
18704 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
18705 my $FParam_N = canonifyName($FParam, "T");
18706 if($FParam_N ne $FParam) {
18707 $Name=~s/\Q$FParam\E/$FParam_N/g;
18708 }
18709 }
18710 }
18711 }
18712 elsif($Type eq "T")
18713 {
18714 my ($ShortTmpl, $TmplParams) = template_Base($Name);
18715
18716 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018717 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018718 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018719 my $FParam = $TParams[0];
18720 foreach my $Pos (1 .. $#TParams)
18721 {
18722 my $TParam = $TParams[$Pos];
18723 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
18724 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
18725 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018726 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018727 }
18728 }
18729 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018730 if($Type eq "S") {
18731 return formatName($Name, "S");
18732 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018733 return $Name;
18734}
18735
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018736sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018737{
18738 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018739 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018740 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018741 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018742 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018743 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018744 next if($tr_name{$Symbol});
18745 $Symbol=~s/[\@\$]+(.*)\Z//;
18746 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018747 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018748 elsif(index($Symbol, "?")==0)
18749 {
18750 next if($tr_name{$Symbol});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018751 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018752 }
18753 else
18754 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018755 $tr_name{$Symbol} = $Symbol;
18756 $mangled_name_gcc{$Symbol} = $Symbol;
18757 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018758 }
18759 }
18760 if($#MnglNames1 > -1)
18761 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018762 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018763 foreach my $MnglName (@MnglNames1)
18764 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018765 if(my $Unmangled = pop(@UnmangledNames))
18766 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040018767 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018768 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
18769 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
18770 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018771 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018772 and $tr_name{$MnglName}=~/vtable for (.+)/)
18773 { # bind class name and v-table symbol
18774 my $ClassName = $1;
18775 $ClassVTable{$ClassName} = $MnglName;
18776 $VTableClass{$MnglName} = $ClassName;
18777 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018778 }
18779 }
18780 }
18781 if($#MnglNames2 > -1)
18782 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018783 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018784 foreach my $MnglName (@MnglNames2)
18785 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018786 if(my $Unmangled = pop(@UnmangledNames))
18787 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018788 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018789 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
18790 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018791 }
18792 }
18793 return \%tr_name;
18794}
18795
18796sub link_symbol($$$)
18797{
18798 my ($Symbol, $RunWith, $Deps) = @_;
18799 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
18800 return 1;
18801 }
18802 if($Deps eq "+Deps")
18803 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018804 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018805 return 1;
18806 }
18807 }
18808 return 0;
18809}
18810
18811sub link_symbol_internal($$$)
18812{
18813 my ($Symbol, $RunWith, $Where) = @_;
18814 return 0 if(not $Where or not $Symbol);
18815 if($Where->{$RunWith}{$Symbol})
18816 { # the exact match by symbol name
18817 return 1;
18818 }
18819 if(my $VSym = $SymVer{$RunWith}{$Symbol})
18820 { # indirect symbol version, i.e.
18821 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018822 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018823 if($Where->{$RunWith}{$VSym}) {
18824 return 1;
18825 }
18826 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018827 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018828 if($Sym and $Ver)
18829 { # search for the symbol with the same version
18830 # or without version
18831 if($Where->{$RunWith}{$Sym})
18832 { # old: foo@v|foo@@v
18833 # new: foo
18834 return 1;
18835 }
18836 if($Where->{$RunWith}{$Sym."\@".$Ver})
18837 { # old: foo|foo@@v
18838 # new: foo@v
18839 return 1;
18840 }
18841 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
18842 { # old: foo|foo@v
18843 # new: foo@@v
18844 return 1;
18845 }
18846 }
18847 return 0;
18848}
18849
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018850sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018851{
18852 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018853 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018854 my @Imported = ();
18855 if($OSgroup eq "macos")
18856 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018857 my $NM = get_CmdPath("nm");
18858 if(not $NM) {
18859 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018860 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018861 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018862 while(<APP>)
18863 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018864 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018865 push(@Imported, $1);
18866 }
18867 }
18868 close(APP);
18869 }
18870 elsif($OSgroup eq "windows")
18871 {
18872 my $DumpBinCmd = get_CmdPath("dumpbin");
18873 if(not $DumpBinCmd) {
18874 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
18875 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018876 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018877 while(<APP>)
18878 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018879 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
18880 push(@Imported, $1);
18881 }
18882 }
18883 close(APP);
18884 }
18885 else
18886 {
18887 my $ReadelfCmd = get_CmdPath("readelf");
18888 if(not $ReadelfCmd) {
18889 exitStatus("Not_Found", "can't find \"readelf\"");
18890 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018891 open(APP, "$ReadelfCmd -Ws \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018892 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018893 while(<APP>)
18894 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018895 if(defined $symtab)
18896 { # do nothing with symtab
18897 if(index($_, "'.dynsym'")!=-1)
18898 { # dynamic table
18899 $symtab = undef;
18900 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018901 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018902 elsif(index($_, "'.symtab'")!=-1)
18903 { # symbol table
18904 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018905 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018906 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018907 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018908 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
18909 if($Ndx eq "UND")
18910 { # only imported symbols
18911 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018912 }
18913 }
18914 }
18915 close(APP);
18916 }
18917 return @Imported;
18918}
18919
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018920my %ELF_BIND = map {$_=>1} (
18921 "WEAK",
18922 "GLOBAL"
18923);
18924
18925my %ELF_TYPE = map {$_=>1} (
18926 "FUNC",
18927 "IFUNC",
18928 "OBJECT",
18929 "COMMON"
18930);
18931
18932my %ELF_VIS = map {$_=>1} (
18933 "DEFAULT",
18934 "PROTECTED"
18935);
18936
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018937sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018938{ # read the line of 'readelf' output corresponding to the symbol
18939 my @Info = split(/\s+/, $_[0]);
18940 # Num: Value Size Type Bind Vis Ndx Name
18941 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018942 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018943 shift(@Info); # spaces
18944 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018945
18946 if($#Info==7)
18947 { # UND SYMBOL (N)
18948 if($Info[7]=~/\(\d+\)/) {
18949 pop(@Info);
18950 }
18951 }
18952
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018953 if($#Info!=6)
18954 { # other lines
18955 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018956 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018957 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018958 return () if(not defined $ELF_BIND{$Info[3]});
18959 return () if(not defined $ELF_VIS{$Info[4]});
18960 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
18961 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
18962 return ();
18963 }
18964 if($OStarget eq "symbian")
18965 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
18966 if(index($Info[6], "_._.absent_export_")!=-1)
18967 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
18968 return ();
18969 }
18970 $Info[6]=~s/\@.+//g; # remove version
18971 }
18972 if(index($Info[2], "0x") == 0)
18973 { # size == 0x3d158
18974 $Info[2] = hex($Info[2]);
18975 }
18976 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018977}
18978
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018979sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018980{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018981 my ($LibVersion, $Name) = @_;
18982 return "" if(not $LibVersion or not $Name);
18983 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
18984 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018985 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018986 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
18987}
18988
18989sub get_LibPath_I($$)
18990{
18991 my ($LibVersion, $Name) = @_;
18992 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018993 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018994 if(-f $Name)
18995 { # absolute path
18996 return $Name;
18997 }
18998 else
18999 { # broken
19000 return "";
19001 }
19002 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019003 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019004 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019005 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019006 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019007 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019008 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019009 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019010 }
19011 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
19012 { # ldconfig default paths
19013 return $DefaultPath;
19014 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019015 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019016 { # search in default linker directories
19017 # and then in all system paths
19018 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019019 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019020 }
19021 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019022 if(not defined $Cache{"checkSystemFiles"}) {
19023 checkSystemFiles();
19024 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019025 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
19026 return $AllObjects[0];
19027 }
19028 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
19029 {
19030 if($ShortName ne $Name)
19031 { # FIXME: check this case
19032 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
19033 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019034 }
19035 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019036 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019037 # can't find
19038 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019039}
19040
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019041sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019042{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019043 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
19044 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019045
19046 my $Real_Path = realpath($Lib_Path);
19047
19048 if(not $Real_Path)
19049 { # broken link
19050 return ();
19051 }
19052
19053 my $Lib_Name = get_filename($Real_Path);
19054
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019055 if($ExtraInfo)
19056 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019057 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019058 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019059 }
19060
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019061 if($IsNeededLib)
19062 {
19063 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
19064 return ();
19065 }
19066 }
19067 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019068 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019069
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019070 if($CheckImpl)
19071 {
19072 if(not $IsNeededLib) {
19073 getImplementations($LibVersion, $Lib_Path);
19074 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019075 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019076
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019077 push(@RecurLib, $Lib_Name);
19078 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019079 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
19080
19081 if(not $IsNeededLib)
19082 { # special cases: libstdc++ and libc
19083 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
19084 {
19085 if($ShortName eq "libstdc++")
19086 { # libstdc++.so.6
19087 $STDCXX_TESTING = 1;
19088 }
19089 elsif($ShortName eq "libc")
19090 { # libc-2.11.3.so
19091 $GLIBC_TESTING = 1;
19092 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019093 }
19094 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019095 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019096 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019097 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019098 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019099 mkpath(get_dirname($DebugPath));
19100 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019101 if($OStarget eq "macos")
19102 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019103 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019104 if(not $NM) {
19105 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019106 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019107 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019108 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019109 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019110 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019111 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019112 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019113 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019114 else
19115 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019116 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019117 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019118 while(<LIB>)
19119 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019120 if($CheckUndefined)
19121 {
19122 if(not $IsNeededLib)
19123 {
19124 if(/ U _([\w\$]+)\s*\Z/)
19125 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019126 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019127 next;
19128 }
19129 }
19130 }
19131
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019132 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019133 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019134 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019135 if($IsNeededLib)
19136 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019137 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019138 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019139 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19140 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019141 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019142 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019143 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019144 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019145 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19146 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019147 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19148 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019149 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019150 setLanguage($LibVersion, "C++");
19151 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019152 }
19153 if($CheckObjectsOnly
19154 and $LibVersion==1) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019155 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019156 }
19157 }
19158 }
19159 }
19160 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019161
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019162 if($Deps)
19163 {
19164 if($LIB_TYPE eq "dynamic")
19165 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019166
19167 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019168 if(not $OtoolCmd) {
19169 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019170 }
19171
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019172 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19173 while(<LIB>)
19174 {
19175 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
19176 and $1 ne $Lib_Path) {
19177 $NeededLib{$1} = 1;
19178 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019179 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019180 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019181 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019182 }
19183 }
19184 elsif($OStarget eq "windows")
19185 { # Windows *.dll, *.lib
19186 my $DumpBinCmd = get_CmdPath("dumpbin");
19187 if(not $DumpBinCmd) {
19188 exitStatus("Not_Found", "can't find \"dumpbin\"");
19189 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019190 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019191 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019192 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019193 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019194 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019195 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019196 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019197 else
19198 { # write to pipe
19199 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019200 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019201 while(<LIB>)
19202 { # 1197 4AC 0000A620 SetThreadStackGuarantee
19203 # 1198 4AD SetThreadToken (forwarded to ...)
19204 # 3368 _o2i_ECPublicKey
19205 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*\Z/i
19206 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
19207 or /\A\s*\d+\s+_([\w\?\@]+)\s*\Z/)
19208 { # dynamic, static and forwarded symbols
19209 my $realname = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019210 if($IsNeededLib)
19211 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019212 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019213 {
19214 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
19215 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
19216 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019217 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019218 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019219 {
19220 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
19221 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019222 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19223 {
19224 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
19225 setLanguage($LibVersion, "C++");
19226 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019227 }
19228 if($CheckObjectsOnly
19229 and $LibVersion==1) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019230 $CheckedSymbols{"Binary"}{$realname} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019231 }
19232 }
19233 }
19234 }
19235 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019236
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019237 if($Deps)
19238 {
19239 if($LIB_TYPE eq "dynamic")
19240 { # dependencies
19241 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19242 while(<LIB>)
19243 {
19244 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
19245 and $1 ne $Lib_Path) {
19246 $NeededLib{path_format($1, $OSgroup)} = 1;
19247 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019248 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019249 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019250 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019251 }
19252 }
19253 else
19254 { # Unix; *.so, *.a
19255 # Symbian: *.dso, *.lib
19256 my $ReadelfCmd = get_CmdPath("readelf");
19257 if(not $ReadelfCmd) {
19258 exitStatus("Not_Found", "can't find \"readelf\"");
19259 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019260 my $Cmd = $ReadelfCmd." -Ws \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019261 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019262 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019263 # write to file
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019264 system($Cmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019265 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019266 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019267 else
19268 { # write to pipe
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019269 open(LIB, $Cmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019270 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019271 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019272 while(<LIB>)
19273 {
19274 if($LIB_TYPE eq "dynamic")
19275 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019276 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019277 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019278 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019279 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019280 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019281 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019282 # do nothing with symtab
19283 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019284 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019285 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019286 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019287 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019288 next;
19289 }
19290 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019291 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019292 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019293 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019294 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019295 if($CheckUndefined)
19296 {
19297 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019298 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019299 }
19300 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019301 next;
19302 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019303 if($Bind eq "WEAK")
19304 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019305 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019306 if($Weak eq "-Weak")
19307 { # skip WEAK symbols
19308 next;
19309 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019310 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019311 my $Short = $Symbol;
19312 $Short=~s/\@.+//g;
19313 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019314 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019315 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
19316 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019317 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019318 if($IsNeededLib)
19319 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019320 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019321 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019322 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19323 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019324 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019325 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019326 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019327 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019328 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19329 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
19330 if($Vers)
19331 {
19332 if($LIB_EXT eq "so")
19333 { # value
19334 $Interface_Value{$LibVersion}{$Symbol} = $Value;
19335 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
19336 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019337 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019338 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19339 {
19340 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19341 setLanguage($LibVersion, "C++");
19342 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019343 }
19344 if($CheckObjectsOnly
19345 and $LibVersion==1) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019346 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019347 }
19348 }
19349 }
19350 }
19351 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019352
19353 if($Deps and $LIB_TYPE eq "dynamic")
19354 { # dynamic library specifics
19355 $Cmd = $ReadelfCmd." -Wd \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
19356 open(LIB, $Cmd." |");
19357
19358 while(<LIB>)
19359 {
19360 if(/NEEDED.+\[([^\[\]]+)\]/)
19361 { # dependencies:
19362 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
19363 $NeededLib{$1} = 1;
19364 }
19365 }
19366
19367 close(LIB);
19368 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019369 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019370 if($Vers)
19371 {
19372 if(not $IsNeededLib and $LIB_EXT eq "so")
19373 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019374 my %Found = ();
19375
19376 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019377 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019378 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019379 next if(index($Symbol,"\@")==-1);
19380 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019381 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019382 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019383 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019384 if($Symbol_SameValue ne $Symbol
19385 and index($Symbol_SameValue,"\@")==-1)
19386 {
19387 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019388 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019389 last;
19390 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019391 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019392 }
19393 }
19394
19395 # default
19396 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19397 {
19398 next if(defined $Found{$Symbol});
19399 next if(index($Symbol,"\@\@")==-1);
19400
19401 if($Symbol=~/\A([^\@]*)\@\@/
19402 and not $SymVer{$LibVersion}{$1})
19403 {
19404 $SymVer{$LibVersion}{$1} = $Symbol;
19405 $Found{$Symbol} = 1;
19406 }
19407 }
19408
19409 # non-default
19410 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19411 {
19412 next if(defined $Found{$Symbol});
19413 next if(index($Symbol,"\@")==-1);
19414
19415 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
19416 and not $SymVer{$LibVersion}{$1})
19417 {
19418 $SymVer{$LibVersion}{$1} = $Symbol;
19419 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019420 }
19421 }
19422 }
19423 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019424 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019425 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019426 foreach my $DyLib (sort keys(%NeededLib))
19427 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019428 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
19429
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019430 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
19431 {
19432 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
19433 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
19434 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019435 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019436 }
19437 }
19438 pop(@RecurLib);
19439 return $Library_Symbol{$LibVersion};
19440}
19441
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019442sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019443{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019444 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019445 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019446 return keys(%Prefixes);
19447}
19448
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019449sub get_prefixes_I($$)
19450{
19451 foreach my $P (@{$_[0]})
19452 {
19453 my @Parts = reverse(split(/[\/\\]+/, $P));
19454 my $Name = $Parts[0];
19455 foreach (1 .. $#Parts)
19456 {
19457 $_[1]->{$Name}{$P} = 1;
19458 last if($_>4 or $Parts[$_] eq "include");
19459 $Name = $Parts[$_].$SLASH.$Name;
19460 }
19461 }
19462}
19463
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019464sub checkSystemFiles()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019465{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019466 $Cache{"checkSystemFiles"} = 1;
19467
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019468 my @SysHeaders = ();
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019469
19470 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019471 {
19472 next if(not -d $DevelPath);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019473
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040019474 my @Files = cmd_find($DevelPath,"f");
19475 foreach my $Link (cmd_find($DevelPath,"l"))
19476 { # add symbolic links
19477 if(-f $Link) {
19478 push(@Files, $Link);
19479 }
19480 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019481
19482 if(not $CheckObjectsOnly)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019483 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019484 # search for headers in /usr/lib
Andrey Ponomarenko13bb0332013-06-28 15:32:28 +040019485 my @Headers = grep { /\.h(pp|xx)?\Z|\/include\// } @Files;
19486 @Headers = grep { not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs|perl|llvm)/ } @Headers;
19487 push(@SysHeaders, @Headers);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019488 }
19489
19490 # search for libraries in /usr/lib (including symbolic links)
19491 my @Libs = grep { /\.$LIB_EXT[0-9.]*\Z/ } @Files;
19492 foreach my $Path (@Libs)
19493 {
19494 my $N = get_filename($Path);
19495 $SystemObjects{$N}{$Path} = 1;
19496 $SystemObjects{parse_libname($N, "name+ext", $OStarget)}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019497 }
19498 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019499
19500 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019501 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019502 foreach my $DevelPath (@{$SystemPaths{"include"}})
19503 {
19504 next if(not -d $DevelPath);
19505 # search for all header files in the /usr/include
19506 # with or without extension (ncurses.h, QtCore, ...)
19507 push(@SysHeaders, cmd_find($DevelPath,"f"));
19508 foreach my $Link (cmd_find($DevelPath,"l"))
19509 { # add symbolic links
19510 if(-f $Link) {
19511 push(@SysHeaders, $Link);
19512 }
19513 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019514 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019515 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019516 }
19517}
19518
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019519sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019520{
19521 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019522 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019523 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
19524 {
19525 if(not -e $Dest) {
19526 exitStatus("Access_Error", "can't access \'$Dest\'");
19527 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019528 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019529 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
19530 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019531 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019532 }
19533 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019534 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019535}
19536
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019537sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019538{
19539 my ($Path, $LibVersion) = @_;
19540 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019541 my $Name = get_filename($Path);
19542 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019543 return 1;
19544 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019545 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019546 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
19547 return 1;
19548 }
19549 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
19550 {
19551 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
19552 return 1;
19553 }
19554 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019555 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019556 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019557 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019558 return 1;
19559 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019560 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019561 return 1;
19562 }
19563 }
19564 return 0;
19565}
19566
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019567sub specificHeader($$)
19568{
19569 my ($Header, $Spec) = @_;
19570 my $Name = get_filename($Header);
19571
19572 if($Spec eq "windows")
19573 {# MS Windows
19574 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
19575 return 1 if($Name=~/([._-]w|win)(32|64)/i);
19576 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
19577 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
19578 my @Dirs = (
19579 "win32",
19580 "win64",
19581 "win",
19582 "windows",
19583 "msvcrt"
19584 ); # /gsf-win32/
19585 if(my $DIRs = join("|", @Dirs)) {
19586 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19587 }
19588 }
19589 elsif($Spec eq "macos")
19590 { # Mac OS
19591 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
19592 }
19593
19594 return 0;
19595}
19596
19597sub skipAlienHeader($)
19598{
19599 my $Path = $_[0];
19600 my $Name = get_filename($Path);
19601 my $Dir = get_dirname($Path);
19602
19603 if($Tolerance=~/2/)
19604 { # 2 - skip internal headers
19605 my @Terms = (
19606 "p",
19607 "priv",
19608 "int",
19609 "impl",
19610 "implementation",
19611 "internal",
19612 "private",
19613 "old",
19614 "compat",
19615 "debug",
19616 "test",
19617 "gen"
19618 );
19619
19620 my @Dirs = (
19621 "private",
19622 "priv",
19623 "port",
19624 "impl",
19625 "internal",
19626 "detail",
19627 "details",
19628 "old",
19629 "compat",
19630 "debug",
19631 "config",
19632 "compiler",
19633 "platform",
19634 "test"
19635 );
19636
19637 if(my $TERMs = join("|", @Terms)) {
19638 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
19639 }
19640 if(my $DIRs = join("|", @Dirs)) {
19641 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19642 }
19643
19644 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
19645 }
19646
19647 if($Tolerance=~/1/)
19648 { # 1 - skip non-Linux headers
19649 if($OSgroup ne "windows")
19650 {
19651 if(specificHeader($Path, "windows")) {
19652 return 1;
19653 }
19654 }
19655 if($OSgroup ne "macos")
19656 {
19657 if(specificHeader($Path, "macos")) {
19658 return 1;
19659 }
19660 }
19661 }
19662
19663 # valid
19664 return 0;
19665}
19666
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019667sub skipHeader($$)
19668{
19669 my ($Path, $LibVersion) = @_;
19670 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019671 if(defined $Cache{"skipHeader"}{$Path}) {
19672 return $Cache{"skipHeader"}{$Path};
19673 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019674 if(defined $Tolerance and $Tolerance=~/1|2/)
19675 { # --tolerant
19676 if(skipAlienHeader($Path)) {
19677 return ($Cache{"skipHeader"}{$Path} = 1);
19678 }
19679 }
19680 if(not keys(%{$SkipHeaders{$LibVersion}})) {
19681 return 0;
19682 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019683 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
19684}
19685
19686sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019687{ # returns:
19688 # 1 - if header should NOT be included and checked
19689 # 2 - if header should NOT be included, but should be checked
19690 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019691 my $Name = get_filename($Path);
19692 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019693 return $Kind;
19694 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019695 foreach my $D (sort {$SkipHeaders{$LibVersion}{"Path"}{$a} cmp $SkipHeaders{$LibVersion}{"Path"}{$b}}
19696 keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019697 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019698 if(index($Path, $D)!=-1)
19699 {
19700 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
19701 return $SkipHeaders{$LibVersion}{"Path"}{$D};
19702 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019703 }
19704 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019705 foreach my $P (sort {$SkipHeaders{$LibVersion}{"Pattern"}{$a} cmp $SkipHeaders{$LibVersion}{"Pattern"}{$b}}
19706 keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019707 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019708 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
19709 {
19710 if($Name=~/$P/) {
19711 return $Kind;
19712 }
19713 if($P=~/[\/\\]/ and $Path=~/$P/) {
19714 return $Kind;
19715 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019716 }
19717 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019718
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019719 return 0;
19720}
19721
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019722sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019723{
19724 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019725 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019726 { # system directory
19727 return;
19728 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019729 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019730 { # already registered
19731 return;
19732 }
19733 foreach my $Path (find_libs($Dir,"",1))
19734 {
19735 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019736 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019737 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019738 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019739 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
19740}
19741
19742sub registerObject($$)
19743{
19744 my ($Path, $LibVersion) = @_;
19745 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019746 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Andrey Ponomarenko27681702012-11-12 16:33:39 +040019747 if($OSgroup=~/linux|bsd/i)
19748 {
19749 if(my $SONAME = getSONAME($Path)) {
19750 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
19751 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019752 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019753 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
19754 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019755 }
19756}
19757
19758sub getSONAME($)
19759{
19760 my $Path = $_[0];
19761 return if(not $Path);
19762 if(defined $Cache{"getSONAME"}{$Path}) {
19763 return $Cache{"getSONAME"}{$Path};
19764 }
19765 my $ObjdumpCmd = get_CmdPath("objdump");
19766 if(not $ObjdumpCmd) {
19767 exitStatus("Not_Found", "can't find \"objdump\"");
19768 }
19769 my $SonameCmd = "$ObjdumpCmd -x $Path 2>$TMP_DIR/null";
19770 if($OSgroup eq "windows") {
19771 $SonameCmd .= " | find \"SONAME\"";
19772 }
19773 else {
19774 $SonameCmd .= " | grep SONAME";
19775 }
19776 if(my $SonameInfo = `$SonameCmd`) {
19777 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
19778 return ($Cache{"getSONAME"}{$Path} = $1);
19779 }
19780 }
19781 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019782}
19783
19784sub getSOPaths_Dest($$)
19785{
19786 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019787 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019788 return ();
19789 }
19790 if(-f $Dest)
19791 {
19792 if(not parse_libname($Dest, "name", $OStarget)) {
19793 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
19794 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019795 registerObject($Dest, $LibVersion);
19796 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019797 return ($Dest);
19798 }
19799 elsif(-d $Dest)
19800 {
19801 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019802 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019803 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019804 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
19805 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019806 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019807 { # all files and symlinks that match the name of a library
19808 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
19809 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019810 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019811 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019812 }
19813 }
19814 }
19815 else
19816 { # search for all files and symlinks
19817 foreach my $Path (find_libs($Dest,"",""))
19818 {
19819 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019820 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019821 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019822 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019823 }
19824 if($OSgroup eq "macos")
19825 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019826 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019827 {
19828 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019829 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019830 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019831 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
19832 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019833 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019834 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019835 }
19836 }
19837 }
19838 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019839 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019840 }
19841 else {
19842 return ();
19843 }
19844}
19845
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019846sub isCyclical($$)
19847{
19848 my ($Stack, $Value) = @_;
19849 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019850}
19851
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019852sub detectWordSize()
19853{
19854 return "" if(not $GCC_PATH);
19855 if($Cache{"detectWordSize"}) {
19856 return $Cache{"detectWordSize"};
19857 }
19858 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019859 my $Defines = `$GCC_PATH -E -dD \"$TMP_DIR/empty.h\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019860 unlink("$TMP_DIR/empty.h");
19861 my $WSize = 0;
19862 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019863 { # GCC 4
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019864 $WSize = $1;
19865 }
19866 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019867 { # GCC 3
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019868 my $PTRDIFF = $1;
19869 if($PTRDIFF=~/long/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019870 $WSize = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019871 }
19872 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019873 $WSize = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019874 }
19875 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019876 if(not $WSize) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019877 exitStatus("Error", "can't check WORD size");
19878 }
19879 return ($Cache{"detectWordSize"} = $WSize);
19880}
19881
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019882sub getWordSize($) {
19883 return $WORD_SIZE{$_[0]};
19884}
19885
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019886sub majorVersion($)
19887{
19888 my $V = $_[0];
19889 return 0 if(not $V);
19890 my @VParts = split(/\./, $V);
19891 return $VParts[0];
19892}
19893
19894sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019895{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019896 my ($V1, $V2) = @_;
19897 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019898 my @V1Parts = split(/\./, $V1);
19899 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019900 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
19901 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019902 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
19903 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
19904 }
19905 return -1 if($#V1Parts < $#V2Parts);
19906 return 1 if($#V1Parts > $#V2Parts);
19907 return 0;
19908}
19909
19910sub read_ABI_Dump($$)
19911{
19912 my ($LibVersion, $Path) = @_;
19913 return if(not $LibVersion or not -e $Path);
19914 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019915 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019916 { # input *.abi
19917 $FilePath = $Path;
19918 }
19919 else
19920 { # input *.abi.tar.gz
19921 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019922 if(not isDump_U($FilePath)) {
19923 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19924 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019925 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019926
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019927 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019928
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019929 my $Line = readLineNum($FilePath, 0);
19930 if($Line=~/xml/)
19931 { # XML format
19932 loadModule("XmlDump");
19933 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019934 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019935 else
19936 { # Perl Data::Dumper format (default)
19937 open(DUMP, $FilePath);
19938 local $/ = undef;
19939 my $Content = <DUMP>;
19940 close(DUMP);
19941
19942 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
19943 { # remove temp file
19944 unlink($FilePath);
19945 }
19946 if($Content!~/};\s*\Z/) {
19947 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19948 }
19949 $ABI = eval($Content);
19950 if(not $ABI) {
19951 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
19952 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019953 }
19954 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019955 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019956 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019957 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019958 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019959 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019960 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019961 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019962
19963 if($ABI->{"ABI_DUMP_VERSION"})
19964 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019965 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019966 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019967 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019968 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019969 }
19970 else
19971 { # support for old ABI dumps
19972 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019973 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019974 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019975 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019976 }
19977 if(majorVersion($DVersion)<2)
19978 { # support for old ABI dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019979 if($UseOldDumps)
19980 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019981 if(cmpVersions($DVersion, $OLDEST_SUPPORTED_VERSION)<0) {
19982 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (older than $OLDEST_SUPPORTED_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019983 }
19984 }
19985 else
19986 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019987 my $Msg = "incompatible version \'$DVersion\' of specified ABI dump (allowed only 2.0<=V<=$ABI_DUMP_VERSION)";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019988 if(cmpVersions($DVersion, $OLDEST_SUPPORTED_VERSION)>=0) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019989 $Msg .= "\nUse -old-dumps option to use old-version dumps ($OLDEST_SUPPORTED_VERSION<=V<2.0)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019990 }
19991 exitStatus("Dump_Version", $Msg);
19992 }
19993 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019994
19995 if(defined $ABI->{"ABI_DUMPER_VERSION"})
19996 { # DWARF ABI Dump
19997 $UseConv_Real{$LibVersion}{"P"} = 1;
19998 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
19999
20000 $UsedDump{$LibVersion}{"DWARF"} = 1;
20001
20002 $TargetComponent = "module";
20003 }
20004
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020005 if(not checkDump($LibVersion, "2.11"))
20006 { # old ABI dumps
20007 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020008 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020009 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020010 { # ABI dump created with --binary option
20011 $UsedDump{$LibVersion}{"BinOnly"} = 1;
20012 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020013 else
20014 { # default
20015 $UsedDump{$LibVersion}{"SrcBin"} = 1;
20016 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020017
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020018 if(defined $ABI->{"Mode"}
20019 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020020 { # --ext option
20021 $ExtendedCheck = 1;
20022 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020023 if($ABI->{"Extra"}) {
20024 $ExtraDump = 1;
20025 }
20026
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020027 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020028 {
20029 $UsedDump{$LibVersion}{"L"} = $Lang;
20030 setLanguage($LibVersion, $Lang);
20031 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020032 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020033 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020034 }
20035 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020036 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020037 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020038 if(not $TInfo)
20039 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020040 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020041 }
20042 my %Tid_TDid = ();
20043 foreach my $TDid (keys(%{$TInfo}))
20044 {
20045 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
20046 {
20047 $MAX_ID = $Tid if($Tid>$MAX_ID);
20048 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020049 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020050 }
20051 }
20052 my %NewID = ();
20053 foreach my $Tid (keys(%Tid_TDid))
20054 {
20055 my @TDids = keys(%{$Tid_TDid{$Tid}});
20056 if($#TDids>=1)
20057 {
20058 foreach my $TDid (@TDids)
20059 {
20060 if($TDid) {
20061 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20062 }
20063 else
20064 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020065 my $ID = ++$MAX_ID;
20066
20067 $NewID{$TDid}{$Tid} = $ID;
20068 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
20069 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020070 }
20071 }
20072 }
20073 else
20074 {
20075 my $TDid = $TDids[0];
20076 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20077 }
20078 }
20079 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
20080 {
20081 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
20082 if(defined $Info{"BaseType"})
20083 {
20084 my $Bid = $Info{"BaseType"}{"Tid"};
20085 my $BDid = $Info{"BaseType"}{"TDid"};
20086 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020087 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020088 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
20089 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
20090 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020091 }
20092 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
20093 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020094 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020095 read_Machine_DumpInfo($ABI, $LibVersion);
20096 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020097 if(not $SymbolInfo{$LibVersion})
20098 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020099 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020100 }
20101 if(not keys(%{$SymbolInfo{$LibVersion}}))
20102 { # validation of old-version dumps
20103 if(not $ExtendedCheck) {
20104 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
20105 }
20106 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020107 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020108 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020109 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020110 else
20111 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020112 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020113 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020114 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020115 }
20116 if(not $DepSymbols)
20117 { # Cannot reconstruct DepSymbols. This may result in false
20118 # positives if the old dump is for library 2. Not a problem if
20119 # old dumps are only from old libraries.
20120 $DepSymbols = {};
20121 }
20122 foreach my $Symbol (keys(%{$DepSymbols})) {
20123 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
20124 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020125 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020126 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
20127 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
20128 $SkipTypes{$LibVersion} = $ABI->{"SkipTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020129 if(not $SkipTypes{$LibVersion})
20130 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020131 $SkipTypes{$LibVersion} = $ABI->{"OpaqueTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020132 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020133 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020134 if(not $SkipSymbols{$LibVersion})
20135 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020136 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020137 }
20138 if(not $SkipSymbols{$LibVersion})
20139 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020140 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020141 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020142 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
20143 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
20144 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020145 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020146 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020147 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020148 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020149 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020150 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020151 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020152 if(not checkDump($LibVersion, "2.10.1")
20153 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020154 { # support for old ABI dumps: added target headers
20155 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020156 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020157 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020158 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020159 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020160 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020161 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020162 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020163 if(defined $ABI->{"GccConstants"})
20164 { # 3.0
20165 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
20166 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
20167 }
20168 }
20169
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020170 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020171 if(not $NestedNameSpaces{$LibVersion})
20172 { # support for old dumps
20173 # Cannot reconstruct NameSpaces. This may affect design
20174 # of the compatibility report.
20175 $NestedNameSpaces{$LibVersion} = {};
20176 }
20177 # target system type
20178 # needed to adopt HTML report
20179 if(not $DumpSystem)
20180 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020181 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020182 }
20183 # recreate environment
20184 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
20185 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020186 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020187 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020188 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20189 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020190 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020191 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020192 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020193 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
20194 {
20195 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
20196 setLanguage($LibVersion, "C++");
20197 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020198 }
20199 }
20200 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020201 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
20202 {
20203 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
20204 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20205 }
20206 }
20207
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020208 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020209 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020210 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020211 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020212 {
20213 if(not $Symbol_Library{$LibVersion}{$MnglName}
20214 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
20215 push(@VFunc, $MnglName);
20216 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020217 }
20218 }
20219 translateSymbols(@VFunc, $LibVersion);
20220 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020221 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
20222
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020223 if(not checkDump($LibVersion, "3.0"))
20224 { # support for old ABI dumps
20225 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20226 {
20227 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
20228 {
20229 if(ref($BaseType) eq "HASH") {
20230 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
20231 }
20232 }
20233 }
20234 }
20235
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020236 if(not checkDump($LibVersion, "3.2"))
20237 { # support for old ABI dumps
20238 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20239 {
20240 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
20241 {
20242 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
20243 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
20244 }
20245 }
20246 }
20247
20248 # repair target headers list
20249 delete($TargetHeaders{$LibVersion});
20250 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020251 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20252 }
20253 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20254 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020255 }
20256
20257 # non-target constants from anon enums
20258 foreach my $Name (keys(%{$Constants{$LibVersion}}))
20259 {
20260 if(not $ExtraDump
20261 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
20262 {
20263 delete($Constants{$LibVersion}{$Name});
20264 }
20265 }
20266 }
20267
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020268 if(not checkDump($LibVersion, "2.20"))
20269 { # support for old ABI dumps
20270 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20271 {
20272 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20273
20274 if($TType=~/Struct|Union|Enum|Typedef/)
20275 { # repair complex types first
20276 next;
20277 }
20278
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020279 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020280 {
20281 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20282 if($BType=~/Struct|Union|Enum/i)
20283 {
20284 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20285 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20286 }
20287 }
20288 }
20289 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20290 {
20291 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20292 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20293 if($TType=~/Struct|Union|Enum/) {
20294 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20295 }
20296 }
20297 }
20298
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020299 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020300 { # order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020301 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20302 { # support for old ABI dumps < 2.0 (ACC 1.22)
20303 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20304 {
20305 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20306 {
20307 if($Access ne "public") {
20308 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20309 }
20310 }
20311 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20312 }
20313 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20314 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020315 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20316 { # support for old ABI dumps
20317 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20318 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020319 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20320 { # DWARF ABI Dumps
20321 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20322 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020323 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20324 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20325 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020326 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20327 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020328 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020329 foreach (keys(%{$TInfo{"Base"}})) {
20330 $Class_SubClasses{$LibVersion}{$_}{$TypeId}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020331 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020332 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020333 if($TInfo{"Type"} eq "MethodPtr")
20334 {
20335 if(defined $TInfo{"Param"})
20336 { # support for old ABI dumps <= 1.17
20337 if(not defined $TInfo{"Param"}{"0"})
20338 {
20339 my $Max = keys(%{$TInfo{"Param"}});
20340 foreach my $Pos (1 .. $Max) {
20341 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20342 }
20343 delete($TInfo{"Param"}{$Max});
20344 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20345 }
20346 }
20347 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020348 if($TInfo{"BaseType"} eq $TypeId)
20349 { # fix ABI dump
20350 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20351 }
20352 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020353 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020354 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020355 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020356 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20357 if(not $BName)
20358 { # broken type
20359 next;
20360 }
20361 if($TInfo{"Name"} eq $BName)
20362 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020363 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020364 next;
20365 }
20366 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20367 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020368 }
20369 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020370 }
20371 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20372 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020373 $TName_Tid{$LibVersion}{formatName($TInfo{"Name"}, "T")} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020374 }
20375 }
20376
20377 if(not checkDump($LibVersion, "2.15"))
20378 { # support for old ABI dumps
20379 my %Dups = ();
20380 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20381 {
20382 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020383 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020384 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20385 { # remove template decls
20386 delete($SymbolInfo{$LibVersion}{$InfoId});
20387 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020388 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020389 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020390 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20391 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020392 { # templates
20393 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020394 }
20395 }
20396 }
20397
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020398 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20399 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020400 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20401 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20402 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20403 { # support for old ABI dumps (< 3.1)
20404 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20405 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20406 { # add "this" first parameter
20407 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20408 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20409
20410 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20411 {
20412 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20413 foreach my $Pos (reverse(0 .. $#Pos)) {
20414 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20415 }
20416 }
20417 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20418 }
20419 }
20420
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020421 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20422 { # ABI dumps have no mangled names for C-functions
20423 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20424 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020425 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20426 { # support for old ABI dumps
20427 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20428 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020429 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20430 { # DWARF ABI Dumps
20431 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20432 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020433 }
20434
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020435 $Descriptor{$LibVersion}{"Dump"} = 1;
20436}
20437
20438sub read_Machine_DumpInfo($$)
20439{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020440 my ($ABI, $LibVersion) = @_;
20441 if($ABI->{"Arch"}) {
20442 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020443 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020444 if($ABI->{"WordSize"}) {
20445 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020446 }
20447 else
20448 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020449 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020450 }
20451 if(not $WORD_SIZE{$LibVersion})
20452 { # support for old dumps (<1.23)
20453 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20454 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020455 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020456 }
20457 else
20458 {
20459 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020460 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020461 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020462 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20463 { # any "pointer"-type
20464 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020465 last;
20466 }
20467 }
20468 if($PSize)
20469 { # a pointer type size
20470 $WORD_SIZE{$LibVersion} = $PSize;
20471 }
20472 else {
20473 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20474 }
20475 }
20476 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020477 if($ABI->{"GccVersion"}) {
20478 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020479 }
20480}
20481
20482sub read_Libs_DumpInfo($$)
20483{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020484 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020485 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20486 if(not $Library_Symbol{$LibVersion})
20487 { # support for old dumps
20488 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20489 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020490 if(keys(%{$Library_Symbol{$LibVersion}})
20491 and not $DumpAPI) {
20492 $Descriptor{$LibVersion}{"Libs"} = "OK";
20493 }
20494}
20495
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020496sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020497{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020498 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020499
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020500 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020501 and not $DumpAPI) {
20502 $Descriptor{$LibVersion}{"Headers"} = "OK";
20503 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020504 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020505 { # headers info is stored in the old dumps in the different way
20506 if($UseOldDumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020507 and my $Name = $ABI->{"Headers"}{$Identity}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020508 { # support for old dumps: headers info corrected in 1.22
20509 $Identity = $Name;
20510 }
20511 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020512 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020513 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020514
20515 if(keys(%{$ABI->{"Sources"}})
20516 and not $DumpAPI) {
20517 $Descriptor{$LibVersion}{"Sources"} = "OK";
20518 }
20519 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
20520 { # headers info is stored in the old dumps in the different way
20521 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20522 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20523 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020524}
20525
20526sub find_libs($$$)
20527{
20528 my ($Path, $Type, $MaxDepth) = @_;
20529 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020530 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020531}
20532
20533sub createDescriptor($$)
20534{
20535 my ($LibVersion, $Path) = @_;
20536 if(not $LibVersion or not $Path
20537 or not -e $Path) {
20538 return "";
20539 }
20540 if(-d $Path)
20541 { # directory with headers files and shared objects
20542 return "
20543 <version>
20544 ".$TargetVersion{$LibVersion}."
20545 </version>
20546
20547 <headers>
20548 $Path
20549 </headers>
20550
20551 <libs>
20552 $Path
20553 </libs>";
20554 }
20555 else
20556 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020557 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020558 { # standard XML-descriptor
20559 return readFile($Path);
20560 }
20561 elsif(is_header($Path, 2, $LibVersion))
20562 { # header file
20563 return "
20564 <version>
20565 ".$TargetVersion{$LibVersion}."
20566 </version>
20567
20568 <headers>
20569 $Path
20570 </headers>
20571
20572 <libs>
20573 none
20574 </libs>";
20575 }
20576 elsif(parse_libname($Path, "name", $OStarget))
20577 { # shared object
20578 return "
20579 <version>
20580 ".$TargetVersion{$LibVersion}."
20581 </version>
20582
20583 <headers>
20584 none
20585 </headers>
20586
20587 <libs>
20588 $Path
20589 </libs>";
20590 }
20591 else
20592 { # standard XML-descriptor
20593 return readFile($Path);
20594 }
20595 }
20596}
20597
20598sub detect_lib_default_paths()
20599{
20600 my %LPaths = ();
20601 if($OSgroup eq "bsd")
20602 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020603 if(my $LdConfig = get_CmdPath("ldconfig"))
20604 {
20605 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
20606 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020607 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
20608 {
20609 my $Name = "lib".$1;
20610 if(not defined $LPaths{$Name}) {
20611 $LPaths{$Name} = $2;
20612 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020613 }
20614 }
20615 }
20616 else {
20617 printMsg("WARNING", "can't find ldconfig");
20618 }
20619 }
20620 else
20621 {
20622 if(my $LdConfig = get_CmdPath("ldconfig"))
20623 {
20624 if($SystemRoot and $OSgroup eq "linux")
20625 { # use host (x86) ldconfig with the target (arm) ld.so.conf
20626 if(-e $SystemRoot."/etc/ld.so.conf") {
20627 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
20628 }
20629 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020630 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
20631 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020632 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
20633 {
20634 my ($Name, $Path) = ($1, $2);
20635 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020636 if(not defined $LPaths{$Name})
20637 { # get first element from the list of available paths
20638
20639 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
20640 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
20641 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
20642
20643 $LPaths{$Name} = $Path;
20644 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020645 }
20646 }
20647 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040020648 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020649 printMsg("WARNING", "can't find ldconfig");
20650 }
20651 }
20652 return \%LPaths;
20653}
20654
20655sub detect_bin_default_paths()
20656{
20657 my $EnvPaths = $ENV{"PATH"};
20658 if($OSgroup eq "beos") {
20659 $EnvPaths.=":".$ENV{"BETOOLS"};
20660 }
20661 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020662 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020663 {
20664 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020665 next if(not $Path);
20666 if($SystemRoot
20667 and $Path=~/\A\Q$SystemRoot\E\//)
20668 { # do NOT use binaries from target system
20669 next;
20670 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020671 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020672 }
20673}
20674
20675sub detect_inc_default_paths()
20676{
20677 return () if(not $GCC_PATH);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020678 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020679 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020680 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020681 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020682 next if(index($Line, "/cc1plus ")!=-1);
20683
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020684 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
20685 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020686 my $Path = realpath($1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020687 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020688 if(index($Path, "c++")!=-1
20689 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020690 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020691 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020692 if(not defined $MAIN_CPP_DIR
20693 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
20694 $MAIN_CPP_DIR = $Path;
20695 }
20696 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020697 elsif(index($Path, "gcc")!=-1) {
20698 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020699 }
20700 else
20701 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020702 if($Path=~/local[\/\\]+include/)
20703 { # local paths
20704 next;
20705 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020706 if($SystemRoot
20707 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
20708 { # The GCC include path for user headers is not a part of the system root
20709 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
20710 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
20711 next;
20712 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020713 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020714 }
20715 }
20716 }
20717 unlink("$TMP_DIR/empty.h");
20718 return %DPaths;
20719}
20720
20721sub detect_default_paths($)
20722{
20723 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
20724 my $Search = $_[0];
20725 if($Search!~/inc/) {
20726 $HSearch = 0;
20727 }
20728 if($Search!~/lib/) {
20729 $LSearch = 0;
20730 }
20731 if($Search!~/bin/) {
20732 $BSearch = 0;
20733 }
20734 if($Search!~/gcc/) {
20735 $GSearch = 0;
20736 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020737 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020738 { # <search_headers> section of the XML descriptor
20739 # do NOT search for systems headers
20740 $HSearch = 0;
20741 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020742 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020743 { # <search_headers> section of the XML descriptor
20744 # do NOT search for systems headers
20745 $LSearch = 0;
20746 }
20747 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
20748 { # additional search paths
20749 next if($Type eq "include" and not $HSearch);
20750 next if($Type eq "lib" and not $LSearch);
20751 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020752 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020753 }
20754 if($OSgroup ne "windows")
20755 { # unix-like
20756 foreach my $Type ("include", "lib", "bin")
20757 { # automatic detection of system "devel" directories
20758 next if($Type eq "include" and not $HSearch);
20759 next if($Type eq "lib" and not $LSearch);
20760 next if($Type eq "bin" and not $BSearch);
20761 my ($UsrDir, $RootDir) = ("/usr", "/");
20762 if($SystemRoot and $Type ne "bin")
20763 { # 1. search for target headers and libraries
20764 # 2. use host commands: ldconfig, readelf, etc.
20765 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
20766 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020767 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020768 if(-d $RootDir."/".$Type)
20769 { # if "/lib" is symbolic link
20770 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020771 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020772 }
20773 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020774 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020775 }
20776 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020777 if(-d $UsrDir)
20778 {
20779 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020780 if(-d $UsrDir."/".$Type)
20781 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020782 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020783 }
20784 }
20785 }
20786 }
20787 if($BSearch)
20788 {
20789 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020790 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020791 }
20792 # check environment variables
20793 if($OSgroup eq "beos")
20794 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020795 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020796 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020797 if($_ eq ".") {
20798 next;
20799 }
20800 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
20801 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
20802 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020803 }
20804 }
20805 if($HSearch)
20806 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020807 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
20808 split(/:|;/, $ENV{"BEINCLUDES"})
20809 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020810 }
20811 if($LSearch)
20812 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020813 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
20814 split(/:|;/, $ENV{"BELIBRARIES"}),
20815 split(/:|;/, $ENV{"LIBRARY_PATH"})
20816 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020817 }
20818 }
20819 if($LSearch)
20820 { # using linker to get system paths
20821 if(my $LPaths = detect_lib_default_paths())
20822 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020823 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020824 foreach my $Name (keys(%{$LPaths}))
20825 {
20826 if($SystemRoot
20827 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
20828 { # wrong ldconfig configuration
20829 # check your <sysroot>/etc/ld.so.conf
20830 next;
20831 }
20832 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020833 if(my $Dir = get_dirname($LPaths->{$Name})) {
20834 $Dirs{$Dir} = 1;
20835 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020836 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020837 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020838 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020839 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020840 }
20841 if($BSearch)
20842 {
20843 if($CrossGcc)
20844 { # --cross-gcc=arm-linux-gcc
20845 if(-e $CrossGcc)
20846 { # absolute or relative path
20847 $GCC_PATH = get_abs_path($CrossGcc);
20848 }
20849 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
20850 { # command name
20851 $GCC_PATH = $CrossGcc;
20852 }
20853 else {
20854 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
20855 }
20856 if($GCC_PATH=~/\s/) {
20857 $GCC_PATH = "\"".$GCC_PATH."\"";
20858 }
20859 }
20860 }
20861 if($GSearch)
20862 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020863 if(not $CrossGcc)
20864 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020865 $GCC_PATH = get_CmdPath("gcc");
20866 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020867 if(not $GCC_PATH)
20868 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020869 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020870 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020871 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020872 { # select the latest version
20873 @GCCs = sort {$b cmp $a} @GCCs;
20874 if(check_gcc($GCCs[0], "3"))
20875 {
20876 $GCC_PATH = $GCCs[0];
20877 last;
20878 }
20879 }
20880 }
20881 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020882 if(not $GCC_PATH) {
20883 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
20884 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020885
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020886 if(not $CheckObjectsOnly_Opt)
20887 {
20888 if(my $GCC_Ver = get_dumpversion($GCC_PATH))
20889 {
20890 my $GccTarget = get_dumpmachine($GCC_PATH);
20891 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget)");
20892 if($GccTarget=~/symbian/)
20893 {
20894 $OStarget = "symbian";
20895 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
20896 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020897
20898 # check GCC version
20899 if($GCC_Ver=~/\A4\.8(|\.0|\.1)\Z/)
20900 { # bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57850
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040020901 # introduced in 4.8
20902 # fixed in 4.9
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020903 printMsg("WARNING", "Not working properly with GCC $GCC_Ver. Please update or downgrade GCC or use a local installation by --gcc-path=PATH option.");
20904 $EMERGENCY_MODE_48 = 1;
20905 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020906 }
20907 else {
20908 exitStatus("Error", "something is going wrong with the GCC compiler");
20909 }
20910 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020911 if($HSearch)
20912 {
20913 if(not $NoStdInc)
20914 { # do NOT search in GCC standard paths
20915 my %DPaths = detect_inc_default_paths();
20916 @DefaultCppPaths = @{$DPaths{"Cpp"}};
20917 @DefaultGccPaths = @{$DPaths{"Gcc"}};
20918 @DefaultIncPaths = @{$DPaths{"Inc"}};
20919 push_U($SystemPaths{"include"}, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020920 }
20921 }
20922 }
20923 if($HSearch)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020924 { # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020925 my $IncPath = "/usr/include";
20926 if($SystemRoot) {
20927 $IncPath = $SystemRoot.$IncPath;
20928 }
20929 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020930 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020931 }
20932 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020933
20934 if($ExtraInfo)
20935 {
20936 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
20937 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
20938 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020939}
20940
20941sub getLIB_EXT($)
20942{
20943 my $Target = $_[0];
20944 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
20945 return $Ext;
20946 }
20947 return $OS_LibExt{$LIB_TYPE}{"default"};
20948}
20949
20950sub getAR_EXT($)
20951{
20952 my $Target = $_[0];
20953 if(my $Ext = $OS_Archive{$Target}) {
20954 return $Ext;
20955 }
20956 return $OS_Archive{"default"};
20957}
20958
20959sub get_dumpversion($)
20960{
20961 my $Cmd = $_[0];
20962 return "" if(not $Cmd);
20963 if($Cache{"get_dumpversion"}{$Cmd}) {
20964 return $Cache{"get_dumpversion"}{$Cmd};
20965 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020966 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020967 chomp($V);
20968 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
20969}
20970
20971sub get_dumpmachine($)
20972{
20973 my $Cmd = $_[0];
20974 return "" if(not $Cmd);
20975 if($Cache{"get_dumpmachine"}{$Cmd}) {
20976 return $Cache{"get_dumpmachine"}{$Cmd};
20977 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020978 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020979 chomp($Machine);
20980 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
20981}
20982
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020983sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020984{
20985 my $Cmd = $_[0];
20986 return "" if(not $Cmd);
20987 my @Options = (
20988 "--version",
20989 "-help"
20990 );
20991 foreach my $Opt (@Options)
20992 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020993 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020994 if($Info) {
20995 return 1;
20996 }
20997 }
20998 return 0;
20999}
21000
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021001sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021002{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021003 my ($Cmd, $ReqVer) = @_;
21004 return 0 if(not $Cmd or not $ReqVer);
21005 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
21006 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021007 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021008 if(my $GccVer = get_dumpversion($Cmd))
21009 {
21010 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
21011 if(cmpVersions($GccVer, $ReqVer)>=0) {
21012 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
21013 }
21014 }
21015 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021016}
21017
21018sub get_depth($)
21019{
21020 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021021 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021022 }
21023 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
21024}
21025
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021026sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021027{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021028 return if($Cache{"registerGccHeaders"}); # this function should be called once
21029
21030 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021031 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021032 my @Headers = cmd_find($Path,"f");
21033 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21034 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021035 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021036 my $FileName = get_filename($HPath);
21037 if(not defined $DefaultGccHeader{$FileName})
21038 { # skip duplicated
21039 $DefaultGccHeader{$FileName} = $HPath;
21040 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021041 }
21042 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021043 $Cache{"registerGccHeaders"} = 1;
21044}
21045
21046sub registerCppHeaders()
21047{
21048 return if($Cache{"registerCppHeaders"}); # this function should be called once
21049
21050 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021051 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021052 my @Headers = cmd_find($CppDir,"f");
21053 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21054 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021055 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021056 my $FileName = get_filename($Path);
21057 if(not defined $DefaultCppHeader{$FileName})
21058 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021059 $DefaultCppHeader{$FileName} = $Path;
21060 }
21061 }
21062 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021063 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021064}
21065
21066sub parse_libname($$$)
21067{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021068 return "" if(not $_[0]);
21069 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
21070 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021071 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021072 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
21073}
21074
21075sub parse_libname_I($$$)
21076{
21077 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021078
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021079 if($Target eq "symbian") {
21080 return parse_libname_symbian($Name, $Type);
21081 }
21082 elsif($Target eq "windows") {
21083 return parse_libname_windows($Name, $Type);
21084 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021085
21086 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021087 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021088 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021089 { # libSDL-1.2.so.0.7.1
21090 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021091 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021092 if($Type eq "name")
21093 { # libSDL-1.2
21094 # libwbxml2
21095 return $2;
21096 }
21097 elsif($Type eq "name+ext")
21098 { # libSDL-1.2.so
21099 # libwbxml2.so
21100 return $1;
21101 }
21102 elsif($Type eq "version")
21103 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021104 if(defined $7
21105 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021106 { # 0.7.1
21107 return $7;
21108 }
21109 else
21110 { # libc-2.5.so (=>2.5 version)
21111 my $MV = $5;
21112 $MV=~s/\A[\-\_]+//g;
21113 return $MV;
21114 }
21115 }
21116 elsif($Type eq "short")
21117 { # libSDL
21118 # libwbxml2
21119 return $3;
21120 }
21121 elsif($Type eq "shortest")
21122 { # SDL
21123 # wbxml
21124 return shortest_name($3);
21125 }
21126 }
21127 return "";# error
21128}
21129
21130sub parse_libname_symbian($$)
21131{
21132 my ($Name, $Type) = @_;
21133 my $Ext = getLIB_EXT("symbian");
21134 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
21135 { # libpthread{00010001}.dso
21136 if($Type eq "name")
21137 { # libpthread{00010001}
21138 return $2;
21139 }
21140 elsif($Type eq "name+ext")
21141 { # libpthread{00010001}.dso
21142 return $1;
21143 }
21144 elsif($Type eq "version")
21145 { # 00010001
21146 my $V = $4;
21147 $V=~s/\{(.+)\}/$1/;
21148 return $V;
21149 }
21150 elsif($Type eq "short")
21151 { # libpthread
21152 return $3;
21153 }
21154 elsif($Type eq "shortest")
21155 { # pthread
21156 return shortest_name($3);
21157 }
21158 }
21159 return "";# error
21160}
21161
21162sub parse_libname_windows($$)
21163{
21164 my ($Name, $Type) = @_;
21165 my $Ext = getLIB_EXT("windows");
21166 if($Name=~/((.+?)\.$Ext)\Z/)
21167 { # netapi32.dll
21168 if($Type eq "name")
21169 { # netapi32
21170 return $2;
21171 }
21172 elsif($Type eq "name+ext")
21173 { # netapi32.dll
21174 return $1;
21175 }
21176 elsif($Type eq "version")
21177 { # DLL version embedded
21178 # at binary-level
21179 return "";
21180 }
21181 elsif($Type eq "short")
21182 { # netapi32
21183 return $2;
21184 }
21185 elsif($Type eq "shortest")
21186 { # netapi
21187 return shortest_name($2);
21188 }
21189 }
21190 return "";# error
21191}
21192
21193sub shortest_name($)
21194{
21195 my $Name = $_[0];
21196 # remove prefix
21197 $Name=~s/\A(lib|open)//;
21198 # remove suffix
21199 $Name=~s/[\W\d_]+\Z//i;
21200 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
21201 return $Name;
21202}
21203
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021204sub createSymbolsList($$$$$)
21205{
21206 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
21207 read_ABI_Dump(1, $DPath);
21208 if(not $CheckObjectsOnly) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021209 prepareSymbols(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021210 }
21211 my %SymbolHeaderLib = ();
21212 my $Total = 0;
21213 # Get List
21214 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
21215 {
21216 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021217 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021218 next;
21219 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021220 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021221 { # skip other symbols
21222 next;
21223 }
21224 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
21225 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021226 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021227 next;
21228 }
21229 my $DyLib = $Symbol_Library{1}{$Symbol};
21230 if(not $DyLib)
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 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
21235 $Total+=1;
21236 }
21237 # Draw List
21238 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
21239 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
21240 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
21241 {
21242 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
21243 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021244 my %NS_Symbol = ();
21245 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021246 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021247 }
21248 foreach my $NameSpace (sort keys(%NS_Symbol))
21249 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021250 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021251 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
21252 foreach my $Symbol (@SortedInterfaces)
21253 {
21254 my $SubReport = "";
21255 my $Signature = get_Signature($Symbol, 1);
21256 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021257 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021258 }
21259 if($Symbol=~/\A(_Z|\?)/)
21260 {
21261 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021262 $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 +040021263 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021264 else {
21265 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21266 }
21267 }
21268 else
21269 {
21270 if($Signature) {
21271 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
21272 }
21273 else {
21274 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21275 }
21276 }
21277 $SYMBOLS_LIST .= $SubReport;
21278 }
21279 }
21280 $SYMBOLS_LIST .= "<br/>\n";
21281 }
21282 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021283 # clear info
21284 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21285 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21286 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21287 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021288 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021289 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021290 my $CssStyles = readModule("Styles", "SymbolsList.css");
21291 my $JScripts = readModule("Scripts", "Sections.js");
21292 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021293 my $Title = "$LName: public symbols";
21294 my $Keywords = "$LName, API, symbols";
21295 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021296 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021297 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021298 <br/><br/><hr/>\n".getReportFooter($LName, 1)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021299 <div style='height:999px;'></div></body></html>";
21300 writeFile($SaveTo, $SYMBOLS_LIST);
21301}
21302
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021303sub add_target_libs($)
21304{
21305 foreach (@{$_[0]}) {
21306 $TargetLibs{$_} = 1;
21307 }
21308}
21309
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021310sub is_target_lib($)
21311{
21312 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021313 if(not $LName) {
21314 return 0;
21315 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021316 if($TargetLibraryName
21317 and $LName!~/\Q$TargetLibraryName\E/) {
21318 return 0;
21319 }
21320 if(keys(%TargetLibs)
21321 and not $TargetLibs{$LName}
21322 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21323 return 0;
21324 }
21325 return 1;
21326}
21327
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021328sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021329{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021330 my ($H, $V) = @_;
21331 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021332 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021333 if($TargetHeaders{$V}{$H}) {
21334 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021335 }
21336 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021337 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021338}
21339
21340sub checkVersionNum($$)
21341{
21342 my ($LibVersion, $Path) = @_;
21343 if(my $VerNum = $TargetVersion{$LibVersion}) {
21344 return $VerNum;
21345 }
21346 my $UsedAltDescr = 0;
21347 foreach my $Part (split(/\s*,\s*/, $Path))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021348 { # try to get version string from file path
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021349 next if(isDump($Part)); # ABI dump
21350 next if($Part=~/\.(xml|desc)\Z/i); # XML descriptor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021351 my $VerNum = "";
21352 if(parse_libname($Part, "name", $OStarget))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021353 {
21354 $UsedAltDescr = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021355 $VerNum = parse_libname($Part, "version", $OStarget);
21356 if(not $VerNum) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021357 $VerNum = readStrVer($Part);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021358 }
21359 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021360 elsif(is_header($Part, 2, $LibVersion) or -d $Part)
21361 {
21362 $UsedAltDescr = 1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021363 $VerNum = readStrVer($Part);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021364 }
21365 if($VerNum ne "")
21366 {
21367 $TargetVersion{$LibVersion} = $VerNum;
21368 if($DumpAPI) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021369 printMsg("WARNING", "setting version number to $VerNum (use -vnum option to change it)");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021370 }
21371 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021372 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 +040021373 }
21374 return $TargetVersion{$LibVersion};
21375 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021376 }
21377 if($UsedAltDescr)
21378 {
21379 if($DumpAPI) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021380 exitStatus("Error", "version number is not set (use -vnum option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021381 }
21382 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021383 exitStatus("Error", ($LibVersion==1?"1st":"2nd")." version number is not set (use -v$LibVersion option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021384 }
21385 }
21386}
21387
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021388sub readStrVer($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021389{
21390 my $Str = $_[0];
21391 return "" if(not $Str);
21392 $Str=~s/\Q$TargetLibraryName\E//g;
21393 if($Str=~/(\/|\\|\w|\A)[\-\_]*(\d+[\d\.\-]+\d+|\d+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021394 { # .../libssh-0.4.0/...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021395 return $2;
21396 }
21397 elsif(my $V = parse_libname($Str, "version", $OStarget)) {
21398 return $V;
21399 }
21400 return "";
21401}
21402
21403sub readLibs($)
21404{
21405 my $LibVersion = $_[0];
21406 if($OStarget eq "windows")
21407 { # dumpbin.exe will crash
21408 # without VS Environment
21409 check_win32_env();
21410 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021411 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021412 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021413 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021414}
21415
21416sub dump_sorting($)
21417{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021418 my $Hash = $_[0];
21419 return [] if(not $Hash);
21420 my @Keys = keys(%{$Hash});
21421 return [] if($#Keys<0);
21422 if($Keys[0]=~/\A\d+\Z/)
21423 { # numbers
21424 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021425 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021426 else
21427 { # strings
21428 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021429 }
21430}
21431
21432sub printMsg($$)
21433{
21434 my ($Type, $Msg) = @_;
21435 if($Type!~/\AINFO/) {
21436 $Msg = $Type.": ".$Msg;
21437 }
21438 if($Type!~/_C\Z/) {
21439 $Msg .= "\n";
21440 }
21441 if($Quiet)
21442 { # --quiet option
21443 appendFile($COMMON_LOG_PATH, $Msg);
21444 }
21445 else
21446 {
21447 if($Type eq "ERROR") {
21448 print STDERR $Msg;
21449 }
21450 else {
21451 print $Msg;
21452 }
21453 }
21454}
21455
21456sub exitStatus($$)
21457{
21458 my ($Code, $Msg) = @_;
21459 printMsg("ERROR", $Msg);
21460 exit($ERROR_CODE{$Code});
21461}
21462
21463sub exitReport()
21464{ # the tool has run without any errors
21465 printReport();
21466 if($COMPILE_ERRORS)
21467 { # errors in headers may add false positives/negatives
21468 exit($ERROR_CODE{"Compile_Error"});
21469 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021470 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21471 { # --binary
21472 exit($ERROR_CODE{"Incompatible"});
21473 }
21474 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21475 { # --source
21476 exit($ERROR_CODE{"Incompatible"});
21477 }
21478 elsif($RESULT{"Source"}{"Problems"}
21479 or $RESULT{"Binary"}{"Problems"})
21480 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021481 exit($ERROR_CODE{"Incompatible"});
21482 }
21483 else {
21484 exit($ERROR_CODE{"Compatible"});
21485 }
21486}
21487
21488sub readRules($)
21489{
21490 my $Kind = $_[0];
21491 if(not -f $RULES_PATH{$Kind}) {
21492 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21493 }
21494 my $Content = readFile($RULES_PATH{$Kind});
21495 while(my $Rule = parseTag(\$Content, "rule"))
21496 {
21497 my $RId = parseTag(\$Rule, "id");
21498 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21499 foreach my $Prop (@Properties) {
21500 if(my $Value = parseTag(\$Rule, lc($Prop)))
21501 {
21502 $Value=~s/\n[ ]*//;
21503 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21504 }
21505 }
21506 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21507 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21508 }
21509 else {
21510 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21511 }
21512 }
21513}
21514
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021515sub getReportPath($)
21516{
21517 my $Level = $_[0];
21518 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21519 if($Level eq "Binary")
21520 {
21521 if($BinaryReportPath)
21522 { # --bin-report-path
21523 return $BinaryReportPath;
21524 }
21525 elsif($OutputReportPath)
21526 { # --report-path
21527 return $OutputReportPath;
21528 }
21529 else
21530 { # default
21531 return $Dir."/abi_compat_report.$ReportFormat";
21532 }
21533 }
21534 elsif($Level eq "Source")
21535 {
21536 if($SourceReportPath)
21537 { # --src-report-path
21538 return $SourceReportPath;
21539 }
21540 elsif($OutputReportPath)
21541 { # --report-path
21542 return $OutputReportPath;
21543 }
21544 else
21545 { # default
21546 return $Dir."/src_compat_report.$ReportFormat";
21547 }
21548 }
21549 else
21550 {
21551 if($OutputReportPath)
21552 { # --report-path
21553 return $OutputReportPath;
21554 }
21555 else
21556 { # default
21557 return $Dir."/compat_report.$ReportFormat";
21558 }
21559 }
21560}
21561
21562sub printStatMsg($)
21563{
21564 my $Level = $_[0];
21565 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21566}
21567
21568sub listAffected($)
21569{
21570 my $Level = $_[0];
21571 my $List = "";
21572 foreach (keys(%{$TotalAffected{$Level}}))
21573 {
21574 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21575 { # skip "Low"-severity problems
21576 next;
21577 }
21578 $List .= "$_\n";
21579 }
21580 my $Dir = get_dirname(getReportPath($Level));
21581 if($Level eq "Binary") {
21582 writeFile($Dir."/abi_affected.txt", $List);
21583 }
21584 elsif($Level eq "Source") {
21585 writeFile($Dir."/src_affected.txt", $List);
21586 }
21587}
21588
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021589sub printReport()
21590{
21591 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021592 createReport();
21593 if($JoinReport or $DoubleReport)
21594 {
21595 if($RESULT{"Binary"}{"Problems"}
21596 or $RESULT{"Source"}{"Problems"}) {
21597 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021598 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021599 else {
21600 printMsg("INFO", "result: COMPATIBLE");
21601 }
21602 printStatMsg("Binary");
21603 printStatMsg("Source");
21604 if($ListAffected)
21605 { # --list-affected
21606 listAffected("Binary");
21607 listAffected("Source");
21608 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021609 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021610 elsif($BinaryOnly)
21611 {
21612 if($RESULT{"Binary"}{"Problems"}) {
21613 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21614 }
21615 else {
21616 printMsg("INFO", "result: COMPATIBLE");
21617 }
21618 printStatMsg("Binary");
21619 if($ListAffected)
21620 { # --list-affected
21621 listAffected("Binary");
21622 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021623 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021624 elsif($SourceOnly)
21625 {
21626 if($RESULT{"Source"}{"Problems"}) {
21627 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
21628 }
21629 else {
21630 printMsg("INFO", "result: COMPATIBLE");
21631 }
21632 printStatMsg("Source");
21633 if($ListAffected)
21634 { # --list-affected
21635 listAffected("Source");
21636 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021637 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021638 if($StdOut)
21639 {
21640 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021641 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021642 printMsg("INFO", "compatibility report has been generated to stdout");
21643 }
21644 else
21645 { # default
21646 printMsg("INFO", "compatibility reports have been generated to stdout");
21647 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021648 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021649 else
21650 {
21651 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021652 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021653 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
21654 }
21655 elsif($DoubleReport)
21656 { # default
21657 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
21658 }
21659 elsif($BinaryOnly)
21660 { # --binary
21661 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
21662 }
21663 elsif($SourceOnly)
21664 { # --source
21665 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
21666 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021667 }
21668}
21669
21670sub check_win32_env()
21671{
21672 if(not $ENV{"DevEnvDir"}
21673 or not $ENV{"LIB"}) {
21674 exitStatus("Error", "can't start without VS environment (vsvars32.bat)");
21675 }
21676}
21677
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021678sub diffSets($$)
21679{
21680 my ($S1, $S2) = @_;
21681 my @SK1 = keys(%{$S1});
21682 my @SK2 = keys(%{$S2});
21683 if($#SK1!=$#SK2) {
21684 return 1;
21685 }
21686 foreach my $K1 (@SK1)
21687 {
21688 if(not defined $S2->{$K1}) {
21689 return 1;
21690 }
21691 }
21692 return 0;
21693}
21694
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021695sub create_ABI_Dump()
21696{
21697 if(not -e $DumpAPI) {
21698 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
21699 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021700 my @DParts = split(/\s*,\s*/, $DumpAPI);
21701 foreach my $Part (@DParts)
21702 {
21703 if(not -e $Part) {
21704 exitStatus("Access_Error", "can't access \'$Part\'");
21705 }
21706 }
21707 checkVersionNum(1, $DumpAPI);
21708 foreach my $Part (@DParts)
21709 {
21710 if(isDump($Part)) {
21711 read_ABI_Dump(1, $Part);
21712 }
21713 else {
21714 readDescriptor(1, createDescriptor(1, $Part));
21715 }
21716 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021717
21718 if(not $Descriptor{1}{"Version"})
21719 { # set to default: X
21720 $Descriptor{1}{"Version"} = "X";
21721 }
21722
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021723 initLogging(1);
21724 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021725
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021726 my $DumpPath = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{1}{"Version"}.".abi";
21727 $DumpPath .= ".".$AR_EXT; # gzipped by default
21728 if($OutputDumpPath)
21729 { # user defined path
21730 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021731 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021732 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
21733
21734 if(not $Archive and not $StdOut)
21735 { # check archive utilities
21736 if($OSgroup eq "windows")
21737 { # using zip
21738 my $ZipCmd = get_CmdPath("zip");
21739 if(not $ZipCmd) {
21740 exitStatus("Not_Found", "can't find \"zip\"");
21741 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021742 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021743 else
21744 { # using tar and gzip
21745 my $TarCmd = get_CmdPath("tar");
21746 if(not $TarCmd) {
21747 exitStatus("Not_Found", "can't find \"tar\"");
21748 }
21749 my $GzipCmd = get_CmdPath("gzip");
21750 if(not $GzipCmd) {
21751 exitStatus("Not_Found", "can't find \"gzip\"");
21752 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021753 }
21754 }
21755
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021756 if(not $Descriptor{1}{"Dump"})
21757 {
21758 if(not $CheckHeadersOnly) {
21759 readLibs(1);
21760 }
21761 if($CheckHeadersOnly) {
21762 setLanguage(1, "C++");
21763 }
21764 if(not $CheckObjectsOnly) {
21765 searchForHeaders(1);
21766 }
21767 $WORD_SIZE{1} = detectWordSize();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021768 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021769 if(not $Descriptor{1}{"Dump"})
21770 {
21771 if($Descriptor{1}{"Headers"}) {
21772 readHeaders(1);
21773 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021774 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021775 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021776 if(not keys(%{$SymbolInfo{1}}))
21777 { # check if created dump is valid
21778 if(not $ExtendedCheck and not $CheckObjectsOnly)
21779 {
21780 if($CheckHeadersOnly) {
21781 exitStatus("Empty_Set", "the set of public symbols is empty");
21782 }
21783 else {
21784 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
21785 }
21786 }
21787 }
21788 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021789 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021790 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
21791 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021792 if($ExtraDump)
21793 { # add unmangled names to the ABI dump
21794 my @Names = ();
21795 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21796 {
21797 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
21798 push(@Names, $MnglName);
21799 }
21800 }
21801 translateSymbols(@Names, 1);
21802 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21803 {
21804 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
21805 {
21806 if(my $Unmangled = $tr_name{$MnglName})
21807 {
21808 if($MnglName ne $Unmangled) {
21809 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
21810 }
21811 }
21812 }
21813 }
21814 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021815
21816 my %GccConstants = (); # built-in GCC constants
21817 foreach my $Name (keys(%{$Constants{1}}))
21818 {
21819 if(not defined $Constants{1}{$Name}{"Header"})
21820 {
21821 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
21822 delete($Constants{1}{$Name});
21823 }
21824 }
21825
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021826 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021827 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021828 "TypeInfo" => $TypeInfo{1},
21829 "SymbolInfo" => $SymbolInfo{1},
21830 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021831 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021832 "SymbolVersion" => $SymVer{1},
21833 "LibraryVersion" => $Descriptor{1}{"Version"},
21834 "LibraryName" => $TargetLibraryName,
21835 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021836 "SkipTypes" => $SkipTypes{1},
21837 "SkipSymbols" => $SkipSymbols{1},
21838 "SkipNameSpaces" => $SkipNameSpaces{1},
21839 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021840 "Headers" => \%HeadersInfo,
21841 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021842 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021843 "NameSpaces" => $NestedNameSpaces{1},
21844 "Target" => $OStarget,
21845 "Arch" => getArch(1),
21846 "WordSize" => $WORD_SIZE{1},
21847 "GccVersion" => get_dumpversion($GCC_PATH),
21848 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
21849 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
21850 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021851 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021852 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021853 }
21854 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021855 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021856 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021857 if($ExtendedCheck)
21858 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021859 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021860 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021861 if($BinaryOnly)
21862 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021863 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021864 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021865 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021866 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021867 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021868 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
21869 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021870 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021871
21872 my $ABI_DUMP = "";
21873 if($UseXML)
21874 {
21875 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021876 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021877 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021878 else
21879 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021880 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021881 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021882 if($StdOut)
21883 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021884 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021885 printMsg("INFO", "ABI dump has been generated to stdout");
21886 return;
21887 }
21888 else
21889 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021890 my ($DDir, $DName) = separate_path($DumpPath);
21891 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021892 if(not $Archive) {
21893 $DPath = $DumpPath;
21894 }
21895
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021896 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021897
21898 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021899 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021900 close(DUMP);
21901
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021902 if(not -s $DPath) {
21903 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
21904 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021905 if($Archive) {
21906 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021907 }
21908
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021909 if($OutputDumpPath) {
21910 printMsg("INFO", "library ABI has been dumped to:\n $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021911 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021912 else {
21913 printMsg("INFO", "library ABI has been dumped to:\n $DumpPath");
21914 }
21915 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 +040021916 }
21917}
21918
21919sub quickEmptyReports()
21920{ # Quick "empty" reports
21921 # 4 times faster than merging equal dumps
21922 # NOTE: the dump contains the "LibraryVersion" attribute
21923 # if you change the version, then your dump will be different
21924 # OVERCOME: use -v1 and v2 options for comparing dumps
21925 # and don't change version in the XML descriptor (and dumps)
21926 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
21927 if(-s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
21928 {
21929 my $FilePath1 = unpackDump($Descriptor{1}{"Path"});
21930 my $FilePath2 = unpackDump($Descriptor{2}{"Path"});
21931 if($FilePath1 and $FilePath2)
21932 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021933 my $Line = readLineNum($FilePath1, 0);
21934 if($Line=~/xml/)
21935 { # XML format
21936 # is not supported yet
21937 return;
21938 }
21939
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021940 local $/ = undef;
21941
21942 open(DUMP1, $FilePath1);
21943 my $Content1 = <DUMP1>;
21944 close(DUMP1);
21945
21946 open(DUMP2, $FilePath2);
21947 my $Content2 = <DUMP2>;
21948 close(DUMP2);
21949
21950 if($Content1 eq $Content2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021951 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021952 # clean memory
21953 undef $Content2;
21954
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021955 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021956 my $ABIdump = eval($Content1);
21957
21958 # clean memory
21959 undef $Content1;
21960
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021961 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021962 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 +040021963 }
21964 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021965 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021966 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
21967 }
21968 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021969 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021970 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
21971 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021972 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021973 read_Libs_DumpInfo($ABIdump, 1);
21974 read_Machine_DumpInfo($ABIdump, 1);
21975 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021976
21977 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
21978 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
21979
21980 %{$CheckedSymbols{"Binary"}} = %{$ABIdump->{"SymbolInfo"}};
21981 %{$CheckedSymbols{"Source"}} = %{$ABIdump->{"SymbolInfo"}};
21982
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021983 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
21984 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
21985 exitReport();
21986 }
21987 }
21988 }
21989}
21990
21991sub initLogging($)
21992{
21993 my $LibVersion = $_[0];
21994 # create log directory
21995 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
21996 if($OutputLogPath{$LibVersion})
21997 { # user-defined by -log-path option
21998 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
21999 }
22000 if($LogMode ne "n") {
22001 mkpath($LOG_DIR);
22002 }
22003 $LOG_PATH{$LibVersion} = get_abs_path($LOG_DIR)."/".$LOG_FILE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022004 if($Debug)
22005 { # debug directory
22006 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022007
22008 if(not $ExtraInfo)
22009 { # enable --extra-info
22010 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
22011 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022012 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022013 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022014}
22015
22016sub writeLog($$)
22017{
22018 my ($LibVersion, $Msg) = @_;
22019 if($LogMode ne "n") {
22020 appendFile($LOG_PATH{$LibVersion}, $Msg);
22021 }
22022}
22023
22024sub resetLogging($)
22025{
22026 my $LibVersion = $_[0];
22027 if($LogMode!~/a|n/)
22028 { # remove old log
22029 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022030 if($Debug) {
22031 rmtree($DEBUG_PATH{$LibVersion});
22032 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022033 }
22034}
22035
22036sub printErrorLog($)
22037{
22038 my $LibVersion = $_[0];
22039 if($LogMode ne "n") {
22040 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
22041 }
22042}
22043
22044sub isDump($)
22045{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022046 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz|\.zip|\.xml|)(\.\w+|)\Z/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022047 return $1;
22048 }
22049 return 0;
22050}
22051
22052sub isDump_U($)
22053{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022054 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)(\.\w+|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022055 return $1;
22056 }
22057 return 0;
22058}
22059
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022060sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022061{
22062 # read input XML descriptors or ABI dumps
22063 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022064 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022065 }
22066 my @DParts1 = split(/\s*,\s*/, $Descriptor{1}{"Path"});
22067 foreach my $Part (@DParts1)
22068 {
22069 if(not -e $Part) {
22070 exitStatus("Access_Error", "can't access \'$Part\'");
22071 }
22072 }
22073 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022074 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022075 }
22076 my @DParts2 = split(/\s*,\s*/, $Descriptor{2}{"Path"});
22077 foreach my $Part (@DParts2)
22078 {
22079 if(not -e $Part) {
22080 exitStatus("Access_Error", "can't access \'$Part\'");
22081 }
22082 }
22083 detect_default_paths("bin"); # to extract dumps
22084 if($#DParts1==0 and $#DParts2==0
22085 and isDump($Descriptor{1}{"Path"})
22086 and isDump($Descriptor{2}{"Path"}))
22087 { # optimization: equal ABI dumps
22088 quickEmptyReports();
22089 }
22090 checkVersionNum(1, $Descriptor{1}{"Path"});
22091 checkVersionNum(2, $Descriptor{2}{"Path"});
22092 printMsg("INFO", "preparation, please wait ...");
22093 foreach my $Part (@DParts1)
22094 {
22095 if(isDump($Part)) {
22096 read_ABI_Dump(1, $Part);
22097 }
22098 else {
22099 readDescriptor(1, createDescriptor(1, $Part));
22100 }
22101 }
22102 foreach my $Part (@DParts2)
22103 {
22104 if(isDump($Part)) {
22105 read_ABI_Dump(2, $Part);
22106 }
22107 else {
22108 readDescriptor(2, createDescriptor(2, $Part));
22109 }
22110 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022111
22112 if(not $Descriptor{1}{"Version"})
22113 { # set to default: X
22114 $Descriptor{1}{"Version"} = "X";
22115 }
22116
22117 if(not $Descriptor{2}{"Version"})
22118 { # set to default: Y
22119 $Descriptor{2}{"Version"} = "Y";
22120 }
22121
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022122 initLogging(1);
22123 initLogging(2);
22124 # check consistency
22125 if(not $Descriptor{1}{"Headers"}
22126 and not $Descriptor{1}{"Libs"}) {
22127 exitStatus("Error", "descriptor d1 does not contain both header files and libraries info");
22128 }
22129 if(not $Descriptor{2}{"Headers"}
22130 and not $Descriptor{2}{"Libs"}) {
22131 exitStatus("Error", "descriptor d2 does not contain both header files and libraries info");
22132 }
22133 if($Descriptor{1}{"Headers"} and not $Descriptor{1}{"Libs"}
22134 and not $Descriptor{2}{"Headers"} and $Descriptor{2}{"Libs"}) {
22135 exitStatus("Error", "can't compare headers with $SLIB_TYPE libraries");
22136 }
22137 elsif(not $Descriptor{1}{"Headers"} and $Descriptor{1}{"Libs"}
22138 and $Descriptor{2}{"Headers"} and not $Descriptor{2}{"Libs"}) {
22139 exitStatus("Error", "can't compare $SLIB_TYPE libraries with headers");
22140 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022141 if(not $Descriptor{1}{"Headers"})
22142 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022143 if($CheckHeadersOnly_Opt) {
22144 exitStatus("Error", "can't find header files info in descriptor d1");
22145 }
22146 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022147 if(not $Descriptor{2}{"Headers"})
22148 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022149 if($CheckHeadersOnly_Opt) {
22150 exitStatus("Error", "can't find header files info in descriptor d2");
22151 }
22152 }
22153 if(not $Descriptor{1}{"Headers"}
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022154 or not $Descriptor{2}{"Headers"})
22155 {
22156 if(not $CheckObjectsOnly_Opt)
22157 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022158 printMsg("WARNING", "comparing $SLIB_TYPE libraries only");
22159 $CheckObjectsOnly = 1;
22160 }
22161 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022162 if(not $Descriptor{1}{"Libs"})
22163 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022164 if($CheckObjectsOnly_Opt) {
22165 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d1");
22166 }
22167 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022168 if(not $Descriptor{2}{"Libs"})
22169 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022170 if($CheckObjectsOnly_Opt) {
22171 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d2");
22172 }
22173 }
22174 if(not $Descriptor{1}{"Libs"}
22175 or not $Descriptor{2}{"Libs"})
22176 { # comparing standalone header files
22177 # comparing ABI dumps created with --headers-only
22178 if(not $CheckHeadersOnly_Opt)
22179 {
22180 printMsg("WARNING", "checking headers only");
22181 $CheckHeadersOnly = 1;
22182 }
22183 }
22184 if($UseDumps)
22185 { # --use-dumps
22186 # parallel processing
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022187 my $DumpPath1 = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{1}{"Version"}.".abi.$AR_EXT";
22188 my $DumpPath2 = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{2}{"Version"}.".abi.$AR_EXT";
22189
22190 unlink($DumpPath1);
22191 unlink($DumpPath2);
22192
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022193 my $pid = fork();
22194 if($pid)
22195 { # dump on two CPU cores
22196 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
22197 if($RelativeDirectory{1}) {
22198 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
22199 }
22200 if($OutputLogPath{1}) {
22201 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
22202 }
22203 if($CrossGcc) {
22204 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22205 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022206 if($Quiet)
22207 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022208 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022209 @PARAMS = (@PARAMS, "-logging-mode", "a");
22210 }
22211 elsif($LogMode and $LogMode ne "w")
22212 { # "w" is default
22213 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022214 }
22215 if($ExtendedCheck) {
22216 @PARAMS = (@PARAMS, "-extended");
22217 }
22218 if($UserLang) {
22219 @PARAMS = (@PARAMS, "-lang", $UserLang);
22220 }
22221 if($TargetVersion{1}) {
22222 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
22223 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022224 if($BinaryOnly) {
22225 @PARAMS = (@PARAMS, "-binary");
22226 }
22227 if($SourceOnly) {
22228 @PARAMS = (@PARAMS, "-source");
22229 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022230 if($SortDump) {
22231 @PARAMS = (@PARAMS, "-sort");
22232 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022233 if($DumpFormat and $DumpFormat ne "perl") {
22234 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22235 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022236 if($CheckHeadersOnly) {
22237 @PARAMS = (@PARAMS, "-headers-only");
22238 }
22239 if($CheckObjectsOnly) {
22240 @PARAMS = (@PARAMS, "-objects-only");
22241 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022242 if($Debug)
22243 {
22244 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022245 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022246 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022247 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022248 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022249 exit(1);
22250 }
22251 }
22252 else
22253 { # child
22254 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
22255 if($RelativeDirectory{2}) {
22256 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
22257 }
22258 if($OutputLogPath{2}) {
22259 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
22260 }
22261 if($CrossGcc) {
22262 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22263 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022264 if($Quiet)
22265 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022266 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022267 @PARAMS = (@PARAMS, "-logging-mode", "a");
22268 }
22269 elsif($LogMode and $LogMode ne "w")
22270 { # "w" is default
22271 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022272 }
22273 if($ExtendedCheck) {
22274 @PARAMS = (@PARAMS, "-extended");
22275 }
22276 if($UserLang) {
22277 @PARAMS = (@PARAMS, "-lang", $UserLang);
22278 }
22279 if($TargetVersion{2}) {
22280 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
22281 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022282 if($BinaryOnly) {
22283 @PARAMS = (@PARAMS, "-binary");
22284 }
22285 if($SourceOnly) {
22286 @PARAMS = (@PARAMS, "-source");
22287 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022288 if($SortDump) {
22289 @PARAMS = (@PARAMS, "-sort");
22290 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022291 if($DumpFormat and $DumpFormat ne "perl") {
22292 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22293 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022294 if($CheckHeadersOnly) {
22295 @PARAMS = (@PARAMS, "-headers-only");
22296 }
22297 if($CheckObjectsOnly) {
22298 @PARAMS = (@PARAMS, "-objects-only");
22299 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022300 if($Debug)
22301 {
22302 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022303 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022304 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022305 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022306 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022307 exit(1);
22308 }
22309 else {
22310 exit(0);
22311 }
22312 }
22313 waitpid($pid, 0);
22314 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022315 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
22316 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022317 if($TargetLibraryFName ne $TargetLibraryName) {
22318 @CMP_PARAMS = (@CMP_PARAMS, "-l-full", $TargetLibraryFName);
22319 }
22320 if($ShowRetVal) {
22321 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
22322 }
22323 if($CrossGcc) {
22324 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
22325 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022326 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
22327 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022328 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022329 }
22330 if($ReportFormat and $ReportFormat ne "html")
22331 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022332 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
22333 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022334 if($OutputReportPath) {
22335 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
22336 }
22337 if($BinaryReportPath) {
22338 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
22339 }
22340 if($SourceReportPath) {
22341 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
22342 }
22343 if($LoggingPath) {
22344 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
22345 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022346 if($CheckHeadersOnly) {
22347 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22348 }
22349 if($CheckObjectsOnly) {
22350 @CMP_PARAMS = (@CMP_PARAMS, "-objects-only");
22351 }
22352 if($BinaryOnly) {
22353 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22354 }
22355 if($SourceOnly) {
22356 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22357 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022358 if($Browse) {
22359 @CMP_PARAMS = (@CMP_PARAMS, "-browse", $Browse);
22360 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022361 if($OpenReport) {
22362 @CMP_PARAMS = (@CMP_PARAMS, "-open");
22363 }
22364 if($Debug)
22365 {
22366 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22367 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022368 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022369 system("perl", $0, @CMP_PARAMS);
22370 exit($?>>8);
22371 }
22372 if(not $Descriptor{1}{"Dump"}
22373 or not $Descriptor{2}{"Dump"})
22374 { # need GCC toolchain to analyze
22375 # header files and libraries
22376 detect_default_paths("inc|lib|gcc");
22377 }
22378 if(not $Descriptor{1}{"Dump"})
22379 {
22380 if(not $CheckHeadersOnly) {
22381 readLibs(1);
22382 }
22383 if($CheckHeadersOnly) {
22384 setLanguage(1, "C++");
22385 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022386 if(not $CheckObjectsOnly) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022387 searchForHeaders(1);
22388 }
22389 $WORD_SIZE{1} = detectWordSize();
22390 }
22391 if(not $Descriptor{2}{"Dump"})
22392 {
22393 if(not $CheckHeadersOnly) {
22394 readLibs(2);
22395 }
22396 if($CheckHeadersOnly) {
22397 setLanguage(2, "C++");
22398 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022399 if(not $CheckObjectsOnly) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022400 searchForHeaders(2);
22401 }
22402 $WORD_SIZE{2} = detectWordSize();
22403 }
22404 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22405 { # support for old ABI dumps
22406 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022407 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022408 {
22409 $WORD_SIZE{1} = $WORD_SIZE{2};
22410 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22411 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022412 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022413 {
22414 $WORD_SIZE{2} = $WORD_SIZE{1};
22415 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22416 }
22417 }
22418 elsif(not $WORD_SIZE{1}
22419 and not $WORD_SIZE{2})
22420 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022421 $WORD_SIZE{1} = "4";
22422 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022423 }
22424 if($Descriptor{1}{"Dump"})
22425 { # support for old ABI dumps
22426 prepareTypes(1);
22427 }
22428 if($Descriptor{2}{"Dump"})
22429 { # support for old ABI dumps
22430 prepareTypes(2);
22431 }
22432 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22433 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22434 }
22435 # started to process input data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022436 if(not $CheckObjectsOnly)
22437 {
22438 if($Descriptor{1}{"Headers"}
22439 and not $Descriptor{1}{"Dump"}) {
22440 readHeaders(1);
22441 }
22442 if($Descriptor{2}{"Headers"}
22443 and not $Descriptor{2}{"Dump"}) {
22444 readHeaders(2);
22445 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022446 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022447
22448 # clean memory
22449 %SystemHeaders = ();
22450 %mangled_name_gcc = ();
22451
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022452 prepareSymbols(1);
22453 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022454
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022455 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022456 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022457
22458 # Virtual Tables
22459 registerVTable(1);
22460 registerVTable(2);
22461
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022462 if(not checkDump(1, "1.22")
22463 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022464 { # support for old ABI dumps
22465 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22466 {
22467 if($ClassName=~/</)
22468 { # templates
22469 if(not defined $VirtualTable{1}{$ClassName})
22470 { # synchronize
22471 delete($VirtualTable{2}{$ClassName});
22472 }
22473 }
22474 }
22475 }
22476
22477 registerOverriding(1);
22478 registerOverriding(2);
22479
22480 setVirtFuncPositions(1);
22481 setVirtFuncPositions(2);
22482
22483 # Other
22484 addParamNames(1);
22485 addParamNames(2);
22486
22487 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022488}
22489
22490sub compareAPIs($)
22491{
22492 my $Level = $_[0];
22493 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022494 loadModule("CallConv");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022495 if($Level eq "Binary") {
22496 printMsg("INFO", "comparing ABIs ...");
22497 }
22498 else {
22499 printMsg("INFO", "comparing APIs ...");
22500 }
22501 if($CheckHeadersOnly
22502 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022503 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022504 detectAdded_H($Level);
22505 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022506 }
22507 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022508 { # added/removed in libs
22509 detectAdded($Level);
22510 detectRemoved($Level);
22511 }
22512 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022513 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022514 mergeSymbols($Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022515 if(keys(%{$CheckedSymbols{$Level}})) {
22516 mergeConstants($Level);
22517 }
22518 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040022519
22520 $Cache{"mergeTypes"} = (); # free memory
22521
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022522 if($CheckHeadersOnly
22523 or $Level eq "Source")
22524 { # added/removed in headers
22525 mergeHeaders($Level);
22526 }
22527 else
22528 { # added/removed in libs
22529 mergeLibs($Level);
22530 if($CheckImpl
22531 and $Level eq "Binary") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022532 mergeImpl();
22533 }
22534 }
22535}
22536
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022537sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022538{
22539 my %Opts = (
22540 "OStarget"=>$OStarget,
22541 "Debug"=>$Debug,
22542 "Quiet"=>$Quiet,
22543 "LogMode"=>$LogMode,
22544 "CheckHeadersOnly"=>$CheckHeadersOnly,
22545
22546 "SystemRoot"=>$SystemRoot,
22547 "MODULES_DIR"=>$MODULES_DIR,
22548 "GCC_PATH"=>$GCC_PATH,
22549 "TargetSysInfo"=>$TargetSysInfo,
22550 "CrossPrefix"=>$CrossPrefix,
22551 "TargetLibraryName"=>$TargetLibraryName,
22552 "CrossGcc"=>$CrossGcc,
22553 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022554 "NoStdInc"=>$NoStdInc,
22555
22556 "BinaryOnly" => $BinaryOnly,
22557 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022558 );
22559 return \%Opts;
22560}
22561
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022562sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022563{
22564 my %CODE_ERROR = reverse(%ERROR_CODE);
22565 return $CODE_ERROR{$_[0]};
22566}
22567
22568sub scenario()
22569{
22570 if($StdOut)
22571 { # enable quiet mode
22572 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022573 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022574 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022575 if(not $LogMode)
22576 { # default
22577 $LogMode = "w";
22578 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022579 if($UserLang)
22580 { # --lang=C++
22581 $UserLang = uc($UserLang);
22582 $COMMON_LANGUAGE{1}=$UserLang;
22583 $COMMON_LANGUAGE{2}=$UserLang;
22584 }
22585 if($LoggingPath)
22586 {
22587 $OutputLogPath{1} = $LoggingPath;
22588 $OutputLogPath{2} = $LoggingPath;
22589 if($Quiet) {
22590 $COMMON_LOG_PATH = $LoggingPath;
22591 }
22592 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040022593 if($Quick) {
22594 $ADD_TMPL_INSTANCES = 0;
22595 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022596 if($OutputDumpPath)
22597 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022598 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022599 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22600 }
22601 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022602 if($BinaryOnly and $SourceOnly)
22603 { # both --binary and --source
22604 # is the default mode
22605 $DoubleReport = 1;
22606 $JoinReport = 0;
22607 $BinaryOnly = 0;
22608 $SourceOnly = 0;
22609 if($OutputReportPath)
22610 { # --report-path
22611 $DoubleReport = 0;
22612 $JoinReport = 1;
22613 }
22614 }
22615 elsif($BinaryOnly or $SourceOnly)
22616 { # --binary or --source
22617 $DoubleReport = 0;
22618 $JoinReport = 0;
22619 }
22620 if($UseXML)
22621 { # --xml option
22622 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022623 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022624 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022625 if($ReportFormat)
22626 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022627 $ReportFormat = lc($ReportFormat);
22628 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022629 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022630 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022631 if($ReportFormat eq "htm")
22632 { # HTM == HTML
22633 $ReportFormat = "html";
22634 }
22635 elsif($ReportFormat eq "xml")
22636 { # --report-format=XML equal to --xml
22637 $UseXML = 1;
22638 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022639 }
22640 else
22641 { # default: HTML
22642 $ReportFormat = "html";
22643 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022644 if($DumpFormat)
22645 { # validate
22646 $DumpFormat = lc($DumpFormat);
22647 if($DumpFormat!~/\A(xml|perl)\Z/) {
22648 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
22649 }
22650 if($DumpFormat eq "xml")
22651 { # --dump-format=XML equal to --xml
22652 $UseXML = 1;
22653 }
22654 }
22655 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022656 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022657 $DumpFormat = "perl";
22658 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022659 if($Quiet and $LogMode!~/a|n/)
22660 { # --quiet log
22661 if(-f $COMMON_LOG_PATH) {
22662 unlink($COMMON_LOG_PATH);
22663 }
22664 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040022665 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022666 $CheckUndefined = 1;
22667 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022668 if($TestTool and $UseDumps)
22669 { # --test && --use-dumps == --test-dump
22670 $TestDump = 1;
22671 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022672 if($Tolerant)
22673 { # enable all
22674 $Tolerance = 1234;
22675 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022676 if($Help)
22677 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022678 HELP_MESSAGE();
22679 exit(0);
22680 }
22681 if($InfoMsg) {
22682 INFO_MESSAGE();
22683 exit(0);
22684 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022685 if($ShowVersion)
22686 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022687 printMsg("INFO", "ABI Compliance Checker (ACC) $TOOL_VERSION\nCopyright (C) 2012 ROSA 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.");
22688 exit(0);
22689 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022690 if($DumpVersion)
22691 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022692 printMsg("INFO", $TOOL_VERSION);
22693 exit(0);
22694 }
22695 if($ExtendedCheck) {
22696 $CheckHeadersOnly = 1;
22697 }
22698 if($SystemRoot_Opt)
22699 { # user defined root
22700 if(not -e $SystemRoot_Opt) {
22701 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
22702 }
22703 $SystemRoot = $SystemRoot_Opt;
22704 $SystemRoot=~s/[\/]+\Z//g;
22705 if($SystemRoot) {
22706 $SystemRoot = get_abs_path($SystemRoot);
22707 }
22708 }
22709 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022710
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022711 if($SortDump)
22712 {
22713 $Data::Dumper::Useperl = 1;
22714 $Data::Dumper::Sortkeys = \&dump_sorting;
22715 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022716
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022717 if($TargetLibsPath)
22718 {
22719 if(not -f $TargetLibsPath) {
22720 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
22721 }
22722 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath))) {
22723 $TargetLibs{$Lib} = 1;
22724 }
22725 }
22726 if($TargetHeadersPath)
22727 { # --headers-list
22728 if(not -f $TargetHeadersPath) {
22729 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
22730 }
22731 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
22732 {
22733 $TargetHeaders{1}{$Header} = 1;
22734 $TargetHeaders{2}{$Header} = 1;
22735 }
22736 }
22737 if($TargetHeader)
22738 { # --header
22739 $TargetHeaders{1}{$TargetHeader} = 1;
22740 $TargetHeaders{2}{$TargetHeader} = 1;
22741 }
22742 if($TestTool
22743 or $TestDump)
22744 { # --test, --test-dump
22745 detect_default_paths("bin|gcc"); # to compile libs
22746 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022747 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
22748 $LIB_EXT, $GCC_PATH, $Browse, $OpenReport, $SortDump, $CheckHeadersOnly, $CheckObjectsOnly);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022749 exit(0);
22750 }
22751 if($DumpSystem)
22752 { # --dump-system
22753 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022754 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022755 { # system XML descriptor
22756 if(not -f $DumpSystem) {
22757 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
22758 }
22759 my $Ret = readSystemDescriptor(readFile($DumpSystem));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022760 foreach (@{$Ret->{"Tools"}})
22761 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022762 push_U($SystemPaths{"bin"}, $_);
22763 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022764 }
22765 if($Ret->{"CrossPrefix"}) {
22766 $CrossPrefix = $Ret->{"CrossPrefix"};
22767 }
22768 }
22769 elsif($SystemRoot_Opt)
22770 { # -sysroot "/" option
22771 # default target: /usr/lib, /usr/include
22772 # search libs: /usr/lib and /lib
22773 if(not -e $SystemRoot."/usr/lib") {
22774 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
22775 }
22776 if(not -e $SystemRoot."/lib") {
22777 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
22778 }
22779 if(not -e $SystemRoot."/usr/include") {
22780 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
22781 }
22782 readSystemDescriptor("
22783 <name>
22784 $DumpSystem
22785 </name>
22786 <headers>
22787 $SystemRoot/usr/include
22788 </headers>
22789 <libs>
22790 $SystemRoot/usr/lib
22791 </libs>
22792 <search_libs>
22793 $SystemRoot/lib
22794 </search_libs>");
22795 }
22796 else {
22797 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
22798 }
22799 detect_default_paths("bin|gcc"); # to check symbols
22800 if($OStarget eq "windows")
22801 { # to run dumpbin.exe
22802 # and undname.exe
22803 check_win32_env();
22804 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022805 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022806 exit(0);
22807 }
22808 if($CmpSystems)
22809 { # --cmp-systems
22810 detect_default_paths("bin"); # to extract dumps
22811 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022812 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022813 exit(0);
22814 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022815 if($GenerateTemplate)
22816 {
22817 writeFile("VERSION.xml", $DescriptorTemplate."\n");
22818 printMsg("INFO", "XML-descriptor template ./VERSION.xml has been generated");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022819 exit(0);
22820 }
22821 if(not $TargetLibraryName) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022822 exitStatus("Error", "library name is not selected (-l option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022823 }
22824 else
22825 { # validate library name
22826 if($TargetLibraryName=~/[\*\/\\]/) {
22827 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
22828 }
22829 }
22830 if(not $TargetLibraryFName) {
22831 $TargetLibraryFName = $TargetLibraryName;
22832 }
22833 if($CheckHeadersOnly_Opt and $CheckObjectsOnly_Opt) {
22834 exitStatus("Error", "you can't specify both -headers-only and -objects-only options at the same time");
22835 }
22836 if($SymbolsListPath)
22837 {
22838 if(not -f $SymbolsListPath) {
22839 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
22840 }
22841 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
22842 $SymbolsList{$Interface} = 1;
22843 }
22844 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022845 if($SkipSymbolsListPath)
22846 {
22847 if(not -f $SkipSymbolsListPath) {
22848 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
22849 }
22850 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath))) {
22851 $SkipSymbolsList{$Interface} = 1;
22852 }
22853 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022854 if($SkipHeadersPath)
22855 {
22856 if(not -f $SkipHeadersPath) {
22857 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
22858 }
22859 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022860 { # register for both versions
22861 $SkipHeadersList{1}{$Path} = 1;
22862 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022863 my ($CPath, $Type) = classifyPath($Path);
22864 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022865 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022866 }
22867 }
22868 if($ParamNamesPath)
22869 {
22870 if(not -f $ParamNamesPath) {
22871 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
22872 }
22873 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
22874 {
22875 if($Line=~s/\A(\w+)\;//)
22876 {
22877 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022878 if($Line=~/;(\d+);/)
22879 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022880 while($Line=~s/(\d+);(\w+)//) {
22881 $AddIntParams{$Interface}{$1}=$2;
22882 }
22883 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022884 else
22885 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022886 my $Num = 0;
22887 foreach my $Name (split(/;/, $Line)) {
22888 $AddIntParams{$Interface}{$Num++}=$Name;
22889 }
22890 }
22891 }
22892 }
22893 }
22894 if($AppPath)
22895 {
22896 if(not -f $AppPath) {
22897 exitStatus("Access_Error", "can't access file \'$AppPath\'");
22898 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022899 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022900 $SymbolsList_App{$Interface} = 1;
22901 }
22902 }
22903 if($DumpAPI)
22904 { # --dump-abi
22905 # make an API dump
22906 create_ABI_Dump();
22907 exit($COMPILE_ERRORS);
22908 }
22909 # default: compare APIs
22910 # -d1 <path>
22911 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022912 compareInit();
22913 if($JoinReport or $DoubleReport)
22914 {
22915 compareAPIs("Binary");
22916 compareAPIs("Source");
22917 }
22918 elsif($BinaryOnly) {
22919 compareAPIs("Binary");
22920 }
22921 elsif($SourceOnly) {
22922 compareAPIs("Source");
22923 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022924 exitReport();
22925}
22926
22927scenario();