blob: ea8d832d646a254c86a5d5d82fd6e80cea1c56ef [file] [log] [blame]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001#!/usr/bin/perl
2###########################################################################
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003# ABI Compliance Checker (ACC) 1.98.7
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)
9# Copyright (C) 2011-2012 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#
39# This program is free software: you can redistribute it and/or modify
40# it under the terms of the GNU General Public License or the GNU Lesser
41# General Public License as published by the Free Software Foundation.
42#
43# This program is distributed in the hope that it will be useful,
44# but WITHOUT ANY WARRANTY; without even the implied warranty of
45# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
46# GNU General Public License for more details.
47#
48# You should have received a copy of the GNU General Public License
49# and the GNU Lesser General Public License along with this program.
50# If not, see <http://www.gnu.org/licenses/>.
51###########################################################################
52use Getopt::Long;
53Getopt::Long::Configure ("posix_default", "no_ignore_case");
54use File::Path qw(mkpath rmtree);
55use File::Temp qw(tempdir);
56use File::Copy qw(copy move);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040057use Cwd qw(abs_path cwd realpath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040058use Data::Dumper;
Andrey Ponomarenko2fba6302012-03-29 17:44:47 +040059use Config;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040060use Fcntl;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040061
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040062my $TOOL_VERSION = "1.98.7";
63my $ABI_DUMP_VERSION = "2.20";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040064my $OLDEST_SUPPORTED_VERSION = "1.18";
65my $XML_REPORT_VERSION = "1.0";
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040066my $XML_ABI_DUMP_VERSION = "1.2";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040067my $OSgroup = get_OSgroup();
68my $ORIG_DIR = cwd();
69my $TMP_DIR = tempdir(CLEANUP=>1);
70
71# Internal modules
72my $MODULES_DIR = get_Modules();
73push(@INC, get_dirname($MODULES_DIR));
74# Rules DB
75my %RULES_PATH = (
76 "Binary" => $MODULES_DIR."/RulesBin.xml",
77 "Source" => $MODULES_DIR."/RulesSrc.xml");
78
79my ($Help, $ShowVersion, %Descriptor, $TargetLibraryName, $GenerateTemplate,
80$TestTool, $DumpAPI, $SymbolsListPath, $CheckHeadersOnly_Opt, $UseDumps,
81$CheckObjectsOnly_Opt, $AppPath, $StrictCompat, $DumpVersion, $ParamNamesPath,
82%RelativeDirectory, $TargetLibraryFName, $TestDump, $CheckImpl, $LoggingPath,
83%TargetVersion, $InfoMsg, $UseOldDumps, %UsedDump, $CrossGcc, %OutputLogPath,
84$OutputReportPath, $OutputDumpPath, $ShowRetVal, $SystemRoot_Opt, $DumpSystem,
85$CmpSystems, $TargetLibsPath, $Debug, $CrossPrefix, $UseStaticLibs, $NoStdInc,
86$TargetComponent_Opt, $TargetSysInfo, $TargetHeader, $ExtendedCheck, $Quiet,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040087$SkipHeadersPath, $CppCompat, $LogMode, $StdOut, $ListAffected, $ReportFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040088$UserLang, $TargetHeadersPath, $BinaryOnly, $SourceOnly, $BinaryReportPath,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040089$SourceReportPath, $UseXML, $Browse, $OpenReport, $SortDump, $DumpFormat,
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040090$ExtraInfo, $ExtraDump, $Force);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040091
92my $CmdName = get_filename($0);
93my %OS_LibExt = (
94 "dynamic" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040095 "linux"=>"so",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040096 "macos"=>"dylib",
97 "windows"=>"dll",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040098 "symbian"=>"dso",
99 "default"=>"so"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400100 },
101 "static" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400102 "linux"=>"a",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400103 "windows"=>"lib",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400104 "symbian"=>"lib",
105 "default"=>"a"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400106 }
107);
108
109my %OS_Archive = (
110 "windows"=>"zip",
111 "default"=>"tar.gz"
112);
113
114my %ERROR_CODE = (
115 # Compatible verdict
116 "Compatible"=>0,
117 "Success"=>0,
118 # Incompatible verdict
119 "Incompatible"=>1,
120 # Undifferentiated error code
121 "Error"=>2,
122 # System command is not found
123 "Not_Found"=>3,
124 # Cannot access input files
125 "Access_Error"=>4,
126 # Cannot compile header files
127 "Cannot_Compile"=>5,
128 # Header compiled with errors
129 "Compile_Error"=>6,
130 # Invalid input ABI dump
131 "Invalid_Dump"=>7,
132 # Incompatible version of ABI dump
133 "Dump_Version"=>8,
134 # Cannot find a module
135 "Module_Error"=>9,
136 # Empty intersection between
137 # headers and shared objects
138 "Empty_Intersection"=>10,
139 # Empty set of symbols in headers
140 "Empty_Set"=>11
141);
142
143my %HomePage = (
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400144 "Wiki"=>"http://ispras.linuxbase.org/index.php/ABI_compliance_checker",
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400145 "Dev1"=>"https://github.com/lvc/abi-compliance-checker",
146 "Dev2"=>"http://forge.ispras.ru/projects/abi-compliance-checker"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400147);
148
149my $ShortUsage = "ABI Compliance Checker (ACC) $TOOL_VERSION
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400150A tool for checking backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400151Copyright (C) 2012 ROSA Laboratory
152License: GNU LGPL or GNU GPL
153
154Usage: $CmdName [options]
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400155Example: $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400156
157OLD.xml and NEW.xml are XML-descriptors:
158
159 <version>
160 1.0
161 </version>
162
163 <headers>
164 /path/to/headers/
165 </headers>
166
167 <libs>
168 /path/to/libraries/
169 </libs>
170
171More info: $CmdName --help\n";
172
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400173if($#ARGV==-1)
174{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400175 printMsg("INFO", $ShortUsage);
176 exit(0);
177}
178
179foreach (2 .. $#ARGV)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400180{ # correct comma separated options
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400181 if($ARGV[$_-1] eq ",")
182 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400183 $ARGV[$_-2].=",".$ARGV[$_];
184 splice(@ARGV, $_-1, 2);
185 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400186 elsif($ARGV[$_-1]=~/,\Z/)
187 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400188 $ARGV[$_-1].=$ARGV[$_];
189 splice(@ARGV, $_, 1);
190 }
191 elsif($ARGV[$_]=~/\A,/
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400192 and $ARGV[$_] ne ",")
193 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400194 $ARGV[$_-1].=$ARGV[$_];
195 splice(@ARGV, $_, 1);
196 }
197}
198
199GetOptions("h|help!" => \$Help,
200 "i|info!" => \$InfoMsg,
201 "v|version!" => \$ShowVersion,
202 "dumpversion!" => \$DumpVersion,
203# general options
204 "l|lib|library=s" => \$TargetLibraryName,
205 "d1|old|o=s" => \$Descriptor{1}{"Path"},
206 "d2|new|n=s" => \$Descriptor{2}{"Path"},
207 "dump|dump-abi|dump_abi=s" => \$DumpAPI,
208 "old-dumps!" => \$UseOldDumps,
209# extra options
210 "d|descriptor-template!" => \$GenerateTemplate,
211 "app|application=s" => \$AppPath,
212 "static-libs!" => \$UseStaticLibs,
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +0400213 "cross-gcc|gcc-path=s" => \$CrossGcc,
214 "cross-prefix|gcc-prefix=s" => \$CrossPrefix,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400215 "sysroot=s" => \$SystemRoot_Opt,
216 "v1|version1|vnum=s" => \$TargetVersion{1},
217 "v2|version2=s" => \$TargetVersion{2},
218 "s|strict!" => \$StrictCompat,
219 "symbols-list=s" => \$SymbolsListPath,
220 "skip-headers=s" => \$SkipHeadersPath,
221 "headers-only|headers_only!" => \$CheckHeadersOnly_Opt,
222 "objects-only!" => \$CheckObjectsOnly_Opt,
223 "check-impl|check-implementation!" => \$CheckImpl,
224 "show-retval!" => \$ShowRetVal,
225 "use-dumps!" => \$UseDumps,
226 "nostdinc!" => \$NoStdInc,
227 "dump-system=s" => \$DumpSystem,
228 "sysinfo=s" => \$TargetSysInfo,
229 "cmp-systems!" => \$CmpSystems,
230 "libs-list=s" => \$TargetLibsPath,
231 "headers-list=s" => \$TargetHeadersPath,
232 "header=s" => \$TargetHeader,
233 "ext|extended!" => \$ExtendedCheck,
234 "q|quiet!" => \$Quiet,
235 "stdout!" => \$StdOut,
236 "report-format=s" => \$ReportFormat,
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400237 "dump-format=s" => \$DumpFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400238 "xml!" => \$UseXML,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400239 "lang=s" => \$UserLang,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400240 "binary|bin|abi!" => \$BinaryOnly,
241 "source|src|api!" => \$SourceOnly,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400242# other options
243 "test!" => \$TestTool,
244 "test-dump!" => \$TestDump,
245 "debug!" => \$Debug,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400246 "cpp-compatible!" => \$CppCompat,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400247 "p|params=s" => \$ParamNamesPath,
248 "relpath1|relpath=s" => \$RelativeDirectory{1},
249 "relpath2=s" => \$RelativeDirectory{2},
250 "dump-path=s" => \$OutputDumpPath,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400251 "sort!" => \$SortDump,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400252 "report-path=s" => \$OutputReportPath,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400253 "bin-report-path=s" => \$BinaryReportPath,
254 "src-report-path=s" => \$SourceReportPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400255 "log-path=s" => \$LoggingPath,
256 "log1-path=s" => \$OutputLogPath{1},
257 "log2-path=s" => \$OutputLogPath{2},
258 "logging-mode=s" => \$LogMode,
259 "list-affected!" => \$ListAffected,
260 "l-full|lib-full=s" => \$TargetLibraryFName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400261 "component=s" => \$TargetComponent_Opt,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400262 "b|browse=s" => \$Browse,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400263 "open!" => \$OpenReport,
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400264 "extra-info=s" => \$ExtraInfo,
265 "extra-dump!" => \$ExtraDump,
266 "force!" => \$Force
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400267) or ERR_MESSAGE();
268
269sub ERR_MESSAGE()
270{
271 printMsg("INFO", "\n".$ShortUsage);
272 exit($ERROR_CODE{"Error"});
273}
274
275my $LIB_TYPE = $UseStaticLibs?"static":"dynamic";
276my $SLIB_TYPE = $LIB_TYPE;
277if($OSgroup!~/macos|windows/ and $SLIB_TYPE eq "dynamic")
278{ # show as "shared" library
279 $SLIB_TYPE = "shared";
280}
281my $LIB_EXT = getLIB_EXT($OSgroup);
282my $AR_EXT = getAR_EXT($OSgroup);
283my $BYTE_SIZE = 8;
284my $COMMON_LOG_PATH = "logs/run.log";
285
286my $HelpMessage="
287NAME:
288 ABI Compliance Checker ($CmdName)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400289 Check backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400290
291DESCRIPTION:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400292 ABI Compliance Checker (ACC) is a tool for checking backward binary and
293 source-level compatibility of a $SLIB_TYPE C/C++ library. The tool checks
294 header files and $SLIB_TYPE libraries (*.$LIB_EXT) of old and new versions and
295 analyzes changes in API and ABI (ABI=API+compiler ABI) that may break binary
296 and/or source-level compatibility: changes in calling stack, v-table changes,
297 removed symbols, renamed fields, etc. Binary incompatibility may result in
298 crashing or incorrect behavior of applications built with an old version of
299 a library if they run on a new one. Source incompatibility may result in
300 recompilation errors with a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400301
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400302 The tool is intended for developers of software libraries and maintainers
303 of operating systems who are interested in ensuring backward compatibility,
304 i.e. allow old applications to run or to be recompiled with newer library
305 versions.
306
307 Also the tool can be used by ISVs for checking applications portability to
308 new library versions. Found issues can be taken into account when adapting
309 the application to a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400310
311 This tool is free software: you can redistribute it and/or modify it
312 under the terms of the GNU LGPL or GNU GPL.
313
314USAGE:
315 $CmdName [options]
316
317EXAMPLE:
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400318 $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400319
320 OLD.xml and NEW.xml are XML-descriptors:
321
322 <version>
323 1.0
324 </version>
325
326 <headers>
327 /path1/to/header(s)/
328 /path2/to/header(s)/
329 ...
330 </headers>
331
332 <libs>
333 /path1/to/library(ies)/
334 /path2/to/library(ies)/
335 ...
336 </libs>
337
338INFORMATION OPTIONS:
339 -h|-help
340 Print this help.
341
342 -i|-info
343 Print complete info.
344
345 -v|-version
346 Print version information.
347
348 -dumpversion
349 Print the tool version ($TOOL_VERSION) and don't do anything else.
350
351GENERAL OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400352 -l|-lib|-library NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400353 Library name (without version).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400354
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400355 -d1|-old|-o PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400356 Descriptor of 1st (old) library version.
357 It may be one of the following:
358
359 1. XML-descriptor (VERSION.xml file):
360
361 <version>
362 1.0
363 </version>
364
365 <headers>
366 /path1/to/header(s)/
367 /path2/to/header(s)/
368 ...
369 </headers>
370
371 <libs>
372 /path1/to/library(ies)/
373 /path2/to/library(ies)/
374 ...
375 </libs>
376
377 ... (XML-descriptor template
378 can be generated by -d option)
379
380 2. ABI dump generated by -dump option
381 3. Directory with headers and/or $SLIB_TYPE libraries
382 4. Single header file
383 5. Single $SLIB_TYPE library
384 6. Comma separated list of headers and/or libraries
385
386 If you are using an 2-6 descriptor types then you should
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400387 specify version numbers with -v1 and -v2 options too.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400388
389 For more information, please see:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400390 http://ispras.linuxbase.org/index.php/Library_Descriptor
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400391
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400392 -d2|-new|-n PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400393 Descriptor of 2nd (new) library version.
394
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400395 -dump|-dump-abi PATH
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400396 Create library ABI dump for the input XML descriptor. You can
397 transfer it anywhere and pass instead of the descriptor. Also
398 it can be used for debugging the tool.
399
400 Supported ABI dump versions: ".majorVersion($ABI_DUMP_VERSION).".0<=V<=$ABI_DUMP_VERSION
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400401
402 -old-dumps
403 Enable support for old-version ABI dumps ($OLDEST_SUPPORTED_VERSION<=V<".majorVersion($ABI_DUMP_VERSION).".0).\n";
404
405sub HELP_MESSAGE() {
406 printMsg("INFO", $HelpMessage."
407MORE INFO:
408 $CmdName --info\n");
409}
410
411sub INFO_MESSAGE()
412{
413 printMsg("INFO", "$HelpMessage
414EXTRA OPTIONS:
415 -d|-descriptor-template
416 Create XML-descriptor template ./VERSION.xml
417
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400418 -app|-application PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400419 This option allows to specify the application that should be checked
420 for portability to the new library version.
421
422 -static-libs
423 Check static libraries instead of the shared ones. The <libs> section
424 of the XML-descriptor should point to static libraries location.
425
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400426 -cross-gcc|-gcc-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400427 Path to the cross GCC compiler to use instead of the usual (host) GCC.
428
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400429 -cross-prefix|-gcc-prefix PREFIX
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400430 GCC toolchain prefix.
431
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400432 -sysroot DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400433 Specify the alternative root directory. The tool will search for include
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400434 paths in the DIR/usr/include and DIR/usr/lib directories.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400435
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400436 -v1|-version1 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400437 Specify 1st library version outside the descriptor. This option is needed
438 if you have prefered an alternative descriptor type (see -d1 option).
439
440 In general case you should specify it in the XML-descriptor:
441 <version>
442 VERSION
443 </version>
444
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400445 -v2|-version2 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400446 Specify 2nd library version outside the descriptor.
447
448 -s|-strict
449 Treat all compatibility warnings as problems. Add a number of \"Low\"
450 severity problems to the return value of the tool.
451
452 -headers-only
453 Check header files without $SLIB_TYPE libraries. It is easy to run, but may
454 provide a low quality compatibility report with false positives and
455 without detecting of added/removed symbols.
456
457 Alternatively you can write \"none\" word to the <libs> section
458 in the XML-descriptor:
459 <libs>
460 none
461 </libs>
462
463 -objects-only
464 Check $SLIB_TYPE libraries without header files. It is easy to run, but may
465 provide a low quality compatibility report with false positives and
466 without analysis of changes in parameters and data types.
467
468 Alternatively you can write \"none\" word to the <headers> section
469 in the XML-descriptor:
470 <headers>
471 none
472 </headers>
473
474 -check-impl|-check-implementation
475 Compare canonified disassembled binary code of $SLIB_TYPE libraries to
476 detect changes in the implementation. Add \'Problems with Implementation\'
477 section to the report.
478
479 -show-retval
480 Show the symbol's return type in the report.
481
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400482 -symbols-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400483 This option allows to specify a file with a list of symbols (mangled
484 names in C++) that should be checked, other symbols will not be checked.
485
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400486 -skip-headers PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400487 The file with the list of header files, that should not be checked.
488
489 -use-dumps
490 Make dumps for two versions of a library and compare dumps. This should
491 increase the performance of the tool and decrease the system memory usage.
492
493 -nostdinc
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400494 Do not search in GCC standard system directories for header files.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400495
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400496 -dump-system NAME -sysroot DIR
497 Find all the shared libraries and header files in DIR directory,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400498 create XML descriptors and make ABI dumps for each library. The result
499 set of ABI dumps can be compared (--cmp-systems) with the other one
500 created for other version of operating system in order to check them for
501 compatibility. Do not forget to specify -cross-gcc option if your target
502 system requires some specific version of GCC compiler (different from
503 the host GCC). The system ABI dump will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400504 sys_dumps/NAME/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400505
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400506 -dump-system DESCRIPTOR.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400507 The same as the previous option but takes an XML descriptor of the target
508 system as input, where you should describe it:
509
510 /* Primary sections */
511
512 <name>
513 /* Name of the system */
514 </name>
515
516 <headers>
517 /* The list of paths to header files and/or
518 directories with header files, one per line */
519 </headers>
520
521 <libs>
522 /* The list of paths to shared libraries and/or
523 directories with shared libraries, one per line */
524 </libs>
525
526 /* Optional sections */
527
528 <search_headers>
529 /* List of directories to be searched
530 for header files to automatically
531 generate include paths, one per line */
532 </search_headers>
533
534 <search_libs>
535 /* List of directories to be searched
536 for shared libraries to resolve
537 dependencies, one per line */
538 </search_libs>
539
540 <tools>
541 /* List of directories with tools used
542 for analysis (GCC toolchain), one per line */
543 </tools>
544
545 <cross_prefix>
546 /* GCC toolchain prefix.
547 Examples:
548 arm-linux-gnueabi
549 arm-none-symbianelf */
550 </cross_prefix>
551
552 <gcc_options>
553 /* Additional GCC options, one per line */
554 </gcc_options>
555
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400556 -sysinfo DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400557 This option may be used with -dump-system to dump ABI of operating
558 systems and configure the dumping process.
559 Default:
560 modules/Targets/{unix, symbian, windows}
561
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400562 -cmp-systems -d1 sys_dumps/NAME1/ARCH -d2 sys_dumps/NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400563 Compare two system ABI dumps. Create compatibility reports for each
564 library and the common HTML report including the summary of test
565 results for all checked libraries. Report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400566 sys_compat_reports/NAME1_to_NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400567
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400568 -libs-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400569 The file with a list of libraries, that should be dumped by
570 the -dump-system option or should be checked by the -cmp-systems option.
571
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400572 -header NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400573 Check/Dump ABI of this header only.
574
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400575 -headers-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400576 The file with a list of headers, that should be checked/dumped.
577
578 -ext|-extended
579 If your library A is supposed to be used by other library B and you
580 want to control the ABI of B, then you should enable this option. The
581 tool will check for changes in all data types, even if they are not
582 used by any function in the library A. Such data types are not part
583 of the A library ABI, but may be a part of the ABI of the B library.
584
585 The short scheme is:
586 app C (broken) -> lib B (broken ABI) -> lib A (stable ABI)
587
588 -q|-quiet
589 Print all messages to the file instead of stdout and stderr.
590 Default path (can be changed by -log-path option):
591 $COMMON_LOG_PATH
592
593 -stdout
594 Print analysis results (compatibility reports and ABI dumps) to stdout
595 instead of creating a file. This would allow piping data to other programs.
596
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400597 -report-format FMT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400598 Change format of compatibility report.
599 Formats:
600 htm - HTML format (default)
601 xml - XML format
602
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400603 -dump-format FMT
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400604 Change format of ABI dump.
605 Formats:
606 perl - Data::Dumper format (default)
607 xml - XML format
608
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400609 -xml
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400610 Alias for: --report-format=xml or --dump-format=xml
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400611
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400612 -lang LANG
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400613 Set library language (C or C++). You can use this option if the tool
614 cannot auto-detect a language. This option may be useful for checking
615 C-library headers (--lang=C) in --headers-only or --extended modes.
616
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400617 -binary|-bin|-abi
618 Show \"Binary\" compatibility problems only.
619 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400620 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400621
622 -source|-src|-api
623 Show \"Source\" compatibility problems only.
624 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400625 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400626
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400627OTHER OPTIONS:
628 -test
629 Run internal tests. Create two binary incompatible versions of a sample
630 library and run the tool to check them for compatibility. This option
631 allows to check if the tool works correctly in the current environment.
632
633 -test-dump
634 Test ability to create, read and compare ABI dumps.
635
636 -debug
637 Debugging mode. Print debug info on the screen. Save intermediate
638 analysis stages in the debug directory:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400639 debug/LIB_NAME/VERSION/
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400640
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400641 Also consider using --dump option for debugging the tool.
642
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400643 -cpp-compatible
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400644 If your header files are written in C language and can be compiled
645 by the G++ compiler (i.e. don't use C++ keywords), then you can tell
646 the tool about this and speedup the analysis.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400647
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400648 -p|-params PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400649 Path to file with the function parameter names. It can be used
650 for improving report view if the library header files have no
651 parameter names. File format:
652
653 func1;param1;param2;param3 ...
654 func2;param1;param2;param3 ...
655 ...
656
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400657 -relpath PATH
658 Replace {RELPATH} macros to PATH in the XML-descriptor used
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400659 for dumping the library ABI (see -dump option).
660
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400661 -relpath1 PATH
662 Replace {RELPATH} macros to PATH in the 1st XML-descriptor (-d1).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400663
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400664 -relpath2 PATH
665 Replace {RELPATH} macros to PATH in the 2nd XML-descriptor (-d2).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400666
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400667 -dump-path PATH
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400668 Specify a *.abi.$AR_EXT or *.abi file path where to generate an ABI dump.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400669 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400670 abi_dumps/LIB_NAME/LIB_NAME_VERSION.abi.$AR_EXT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400671
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400672 -sort
673 Enable sorting of data in ABI dumps.
674
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400675 -report-path PATH
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400676 Path to compatibility report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400677 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400678 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400679
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400680 -bin-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400681 Path to \"Binary\" compatibility report.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400682 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400683 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400684
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400685 -src-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400686 Path to \"Source\" compatibility report.
687 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400688 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400689
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400690 -log-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400691 Log path for all messages.
692 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400693 logs/LIB_NAME/VERSION/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400694
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400695 -log1-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400696 Log path for 1st version of a library.
697 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400698 logs/LIB_NAME/V1/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400699
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400700 -log2-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400701 Log path for 2nd version of a library.
702 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400703 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400704
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400705 -logging-mode MODE
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400706 Change logging mode.
707 Modes:
708 w - overwrite old logs (default)
709 a - append old logs
710 n - do not write any logs
711
712 -list-affected
713 Generate file with the list of incompatible
714 symbols beside the HTML compatibility report.
715 Use 'c++filt \@file' command from GNU binutils
716 to unmangle C++ symbols in the generated file.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400717 Default names:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400718 abi_affected.txt
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400719 src_affected.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400720
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400721 -component NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400722 The component name in the title and summary of the HTML report.
723 Default:
724 library
725
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400726 -l-full|-lib-full NAME
727 Change library name in the report title to NAME. By default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400728 will be displayed a name specified by -l option.
729
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400730 -b|-browse PROGRAM
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400731 Open report(s) in the browser (firefox, opera, etc.).
732
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400733 -open
734 Open report(s) in the default browser.
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400735
736 -extra-info DIR
737 Dump extra info to DIR.
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400738
739 -extra-dump
740 Create extended ABI dump containing all symbols
741 from the translation unit.
742
743 -force
744 Try to use this option if the tool doesn't work.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400745
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400746REPORT:
747 Compatibility report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400748 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400749
750 Log will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400751 logs/LIB_NAME/V1/log.txt
752 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400753
754EXIT CODES:
755 0 - Compatible. The tool has run without any errors.
756 non-zero - Incompatible or the tool has run with errors.
757
758REPORT BUGS TO:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400759 Andrey Ponomarenko <aponomarenko\@rosalab.ru>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400760
761MORE INFORMATION:
762 ".$HomePage{"Wiki"}."
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400763 ".$HomePage{"Dev1"}."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400764}
765
766my $DescriptorTemplate = "
767<?xml version=\"1.0\" encoding=\"utf-8\"?>
768<descriptor>
769
770/* Primary sections */
771
772<version>
773 /* Version of the library */
774</version>
775
776<headers>
777 /* The list of paths to header files and/or
778 directories with header files, one per line */
779</headers>
780
781<libs>
782 /* The list of paths to shared libraries (*.$LIB_EXT) and/or
783 directories with shared libraries, one per line */
784</libs>
785
786/* Optional sections */
787
788<include_paths>
789 /* The list of include paths that will be provided
790 to GCC to compile library headers, one per line.
791 NOTE: If you define this section then the tool
792 will not automatically generate include paths */
793</include_paths>
794
795<add_include_paths>
796 /* The list of include paths that will be added
797 to the automatically generated include paths, one per line */
798</add_include_paths>
799
800<skip_include_paths>
801 /* The list of include paths that will be removed from the
802 list of automatically generated include paths, one per line */
803</skip_include_paths>
804
805<gcc_options>
806 /* Additional GCC options, one per line */
807</gcc_options>
808
809<include_preamble>
810 /* The list of header files that will be
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +0400811 included before other headers, one per line */
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400812</include_preamble>
813
814<defines>
815 /* The list of defines that will be added at the
816 headers compiling stage, one per line:
817 #define A B
818 #define C D */
819</defines>
820
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +0400821<add_namespaces>
822 /* The list of namespaces that should be added to the alanysis
823 if the tool cannot find them automatically, one per line */
824</add_namespaces>
825
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400826<skip_types>
827 /* The list of data types, that
828 should not be checked, one per line */
829</skip_types>
830
831<skip_symbols>
832 /* The list of functions (mangled/symbol names in C++),
833 that should not be checked, one per line */
834</skip_symbols>
835
836<skip_namespaces>
837 /* The list of C++ namespaces, that
838 should not be checked, one per line */
839</skip_namespaces>
840
841<skip_constants>
842 /* The list of constants that should
843 not be checked, one name per line */
844</skip_constants>
845
846<skip_headers>
847 /* The list of header files and/or directories
848 with header files that should not be checked, one per line */
849</skip_headers>
850
851<skip_libs>
852 /* The list of shared libraries and/or directories
853 with shared libraries that should not be checked, one per line */
854</skip_libs>
855
856<skip_including>
857 /* The list of header files, that cannot be included
858 directly (or non-self compiled ones), one per line */
859</skip_including>
860
861<search_headers>
862 /* List of directories to be searched
863 for header files to automatically
864 generate include paths, one per line. */
865</search_headers>
866
867<search_libs>
868 /* List of directories to be searched
869 for shared librariess to resolve
870 dependencies, one per line */
871</search_libs>
872
873<tools>
874 /* List of directories with tools used
875 for analysis (GCC toolchain), one per line */
876</tools>
877
878<cross_prefix>
879 /* GCC toolchain prefix.
880 Examples:
881 arm-linux-gnueabi
882 arm-none-symbianelf */
883</cross_prefix>
884
885</descriptor>";
886
887my %Operator_Indication = (
888 "not" => "~",
889 "assign" => "=",
890 "andassign" => "&=",
891 "orassign" => "|=",
892 "xorassign" => "^=",
893 "or" => "|",
894 "xor" => "^",
895 "addr" => "&",
896 "and" => "&",
897 "lnot" => "!",
898 "eq" => "==",
899 "ne" => "!=",
900 "lt" => "<",
901 "lshift" => "<<",
902 "lshiftassign" => "<<=",
903 "rshiftassign" => ">>=",
904 "call" => "()",
905 "mod" => "%",
906 "modassign" => "%=",
907 "subs" => "[]",
908 "land" => "&&",
909 "lor" => "||",
910 "rshift" => ">>",
911 "ref" => "->",
912 "le" => "<=",
913 "deref" => "*",
914 "mult" => "*",
915 "preinc" => "++",
916 "delete" => " delete",
917 "vecnew" => " new[]",
918 "vecdelete" => " delete[]",
919 "predec" => "--",
920 "postinc" => "++",
921 "postdec" => "--",
922 "plusassign" => "+=",
923 "plus" => "+",
924 "minus" => "-",
925 "minusassign" => "-=",
926 "gt" => ">",
927 "ge" => ">=",
928 "new" => " new",
929 "multassign" => "*=",
930 "divassign" => "/=",
931 "div" => "/",
932 "neg" => "-",
933 "pos" => "+",
934 "memref" => "->*",
935 "compound" => "," );
936
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400937my %UnknownOperator;
938
939my %NodeType= (
940 "array_type" => "Array",
941 "binfo" => "Other",
942 "boolean_type" => "Intrinsic",
943 "complex_type" => "Intrinsic",
944 "const_decl" => "Other",
945 "enumeral_type" => "Enum",
946 "field_decl" => "Other",
947 "function_decl" => "Other",
948 "function_type" => "FunctionType",
949 "identifier_node" => "Other",
950 "integer_cst" => "Other",
951 "integer_type" => "Intrinsic",
952 "method_type" => "MethodType",
953 "namespace_decl" => "Other",
954 "parm_decl" => "Other",
955 "pointer_type" => "Pointer",
956 "real_cst" => "Other",
957 "real_type" => "Intrinsic",
958 "record_type" => "Struct",
959 "reference_type" => "Ref",
960 "string_cst" => "Other",
961 "template_decl" => "Other",
962 "template_type_parm" => "Other",
963 "tree_list" => "Other",
964 "tree_vec" => "Other",
965 "type_decl" => "Other",
966 "union_type" => "Union",
967 "var_decl" => "Other",
968 "void_type" => "Intrinsic",
969 # "nop_expr" => "Other",
970 # "addr_expr" => "Other",
971 "offset_type" => "Other" );
972
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400973my %CppKeywords_C = map {$_=>1} (
974 # C++ 2003 keywords
975 "public",
976 "protected",
977 "private",
978 "default",
979 "template",
980 "new",
981 #"asm",
982 "dynamic_cast",
983 "auto",
984 "try",
985 "namespace",
986 "typename",
987 "using",
988 "reinterpret_cast",
989 "friend",
990 "class",
991 "virtual",
992 "const_cast",
993 "mutable",
994 "static_cast",
995 "export",
996 # C++0x keywords
997 "noexcept",
998 "nullptr",
999 "constexpr",
1000 "static_assert",
1001 "explicit",
1002 # cannot be used as a macro name
1003 # as it is an operator in C++
1004 "and",
1005 #"and_eq",
1006 "not",
1007 #"not_eq",
1008 "or"
1009 #"or_eq",
1010 #"bitand",
1011 #"bitor",
1012 #"xor",
1013 #"xor_eq",
1014 #"compl"
1015);
1016
1017my %CppKeywords_F = map {$_=>1} (
1018 "delete",
1019 "catch",
1020 "alignof",
1021 "thread_local",
1022 "decltype",
1023 "typeid"
1024);
1025
1026my %CppKeywords_O = map {$_=>1} (
1027 "bool",
1028 "register",
1029 "inline",
1030 "operator"
1031);
1032
1033my %CppKeywords_A = map {$_=>1} (
1034 "this",
1035 "throw"
1036);
1037
1038foreach (keys(%CppKeywords_C),
1039keys(%CppKeywords_F),
1040keys(%CppKeywords_O)) {
1041 $CppKeywords_A{$_}=1;
1042}
1043
1044# Header file extensions as described by gcc
1045my $HEADER_EXT = "h|hh|hp|hxx|hpp|h\\+\\+";
1046
1047my %IntrinsicMangling = (
1048 "void" => "v",
1049 "bool" => "b",
1050 "wchar_t" => "w",
1051 "char" => "c",
1052 "signed char" => "a",
1053 "unsigned char" => "h",
1054 "short" => "s",
1055 "unsigned short" => "t",
1056 "int" => "i",
1057 "unsigned int" => "j",
1058 "long" => "l",
1059 "unsigned long" => "m",
1060 "long long" => "x",
1061 "__int64" => "x",
1062 "unsigned long long" => "y",
1063 "__int128" => "n",
1064 "unsigned __int128" => "o",
1065 "float" => "f",
1066 "double" => "d",
1067 "long double" => "e",
1068 "__float80" => "e",
1069 "__float128" => "g",
1070 "..." => "z"
1071);
1072
1073my %StdcxxMangling = (
1074 "3std"=>"St",
1075 "3std9allocator"=>"Sa",
1076 "3std12basic_string"=>"Sb",
1077 "3std12basic_stringIcE"=>"Ss",
1078 "3std13basic_istreamIcE"=>"Si",
1079 "3std13basic_ostreamIcE"=>"So",
1080 "3std14basic_iostreamIcE"=>"Sd"
1081);
1082
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04001083my $DEFAULT_STD_PARMS = "std::(allocator|less|char_traits|regex_traits|istreambuf_iterator|ostreambuf_iterator)";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001084
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001085my %ConstantSuffix = (
1086 "unsigned int"=>"u",
1087 "long"=>"l",
1088 "unsigned long"=>"ul",
1089 "long long"=>"ll",
1090 "unsigned long long"=>"ull"
1091);
1092
1093my %ConstantSuffixR =
1094reverse(%ConstantSuffix);
1095
1096my %OperatorMangling = (
1097 "~" => "co",
1098 "=" => "aS",
1099 "|" => "or",
1100 "^" => "eo",
1101 "&" => "an",#ad (addr)
1102 "==" => "eq",
1103 "!" => "nt",
1104 "!=" => "ne",
1105 "<" => "lt",
1106 "<=" => "le",
1107 "<<" => "ls",
1108 "<<=" => "lS",
1109 ">" => "gt",
1110 ">=" => "ge",
1111 ">>" => "rs",
1112 ">>=" => "rS",
1113 "()" => "cl",
1114 "%" => "rm",
1115 "[]" => "ix",
1116 "&&" => "aa",
1117 "||" => "oo",
1118 "*" => "ml",#de (deref)
1119 "++" => "pp",#
1120 "--" => "mm",#
1121 "new" => "nw",
1122 "delete" => "dl",
1123 "new[]" => "na",
1124 "delete[]" => "da",
1125 "+=" => "pL",
1126 "+" => "pl",#ps (pos)
1127 "-" => "mi",#ng (neg)
1128 "-=" => "mI",
1129 "*=" => "mL",
1130 "/=" => "dV",
1131 "&=" => "aN",
1132 "|=" => "oR",
1133 "%=" => "rM",
1134 "^=" => "eO",
1135 "/" => "dv",
1136 "->*" => "pm",
1137 "->" => "pt",#rf (ref)
1138 "," => "cm",
1139 "?" => "qu",
1140 "." => "dt",
1141 "sizeof"=> "sz"#st
1142);
1143
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001144my %Intrinsic_Keywords = map {$_=>1} (
1145 "true",
1146 "false",
1147 "_Bool",
1148 "_Complex",
1149 "const",
1150 "int",
1151 "long",
1152 "void",
1153 "short",
1154 "float",
1155 "volatile",
1156 "restrict",
1157 "unsigned",
1158 "signed",
1159 "char",
1160 "double",
1161 "class",
1162 "struct",
1163 "union",
1164 "enum"
1165);
1166
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001167my %GlibcHeader = map {$_=>1} (
1168 "aliases.h",
1169 "argp.h",
1170 "argz.h",
1171 "assert.h",
1172 "cpio.h",
1173 "ctype.h",
1174 "dirent.h",
1175 "envz.h",
1176 "errno.h",
1177 "error.h",
1178 "execinfo.h",
1179 "fcntl.h",
1180 "fstab.h",
1181 "ftw.h",
1182 "glob.h",
1183 "grp.h",
1184 "iconv.h",
1185 "ifaddrs.h",
1186 "inttypes.h",
1187 "langinfo.h",
1188 "limits.h",
1189 "link.h",
1190 "locale.h",
1191 "malloc.h",
1192 "math.h",
1193 "mntent.h",
1194 "monetary.h",
1195 "nl_types.h",
1196 "obstack.h",
1197 "printf.h",
1198 "pwd.h",
1199 "regex.h",
1200 "sched.h",
1201 "search.h",
1202 "setjmp.h",
1203 "shadow.h",
1204 "signal.h",
1205 "spawn.h",
1206 "stdarg.h",
1207 "stdint.h",
1208 "stdio.h",
1209 "stdlib.h",
1210 "string.h",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001211 "strings.h",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001212 "tar.h",
1213 "termios.h",
1214 "time.h",
1215 "ulimit.h",
1216 "unistd.h",
1217 "utime.h",
1218 "wchar.h",
1219 "wctype.h",
1220 "wordexp.h" );
1221
1222my %GlibcDir = map {$_=>1} (
1223 "arpa",
1224 "bits",
1225 "gnu",
1226 "netinet",
1227 "net",
1228 "nfs",
1229 "rpc",
1230 "sys",
1231 "linux" );
1232
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001233my %WinHeaders = map {$_=>1} (
1234 "dos.h",
1235 "process.h",
1236 "winsock.h",
1237 "config-win.h",
1238 "mem.h",
1239 "windows.h",
1240 "winsock2.h",
1241 "crtdbg.h",
1242 "ws2tcpip.h"
1243);
1244
1245my %ObsoleteHeaders = map {$_=>1} (
1246 "iostream.h",
1247 "fstream.h"
1248);
1249
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001250my %AlienHeaders = map {$_=>1} (
1251 # Solaris
1252 "thread.h",
1253 "sys/atomic.h",
1254 # HPUX
1255 "sys/stream.h",
1256 # Symbian
1257 "AknDoc.h",
1258 # Atari ST
1259 "ext.h",
1260 "tos.h",
1261 # MS-DOS
1262 "alloc.h",
1263 # Sparc
1264 "sys/atomic.h"
1265);
1266
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001267my %ConfHeaders = map {$_=>1} (
1268 "atomic",
1269 "conf.h",
1270 "config.h",
1271 "configure.h",
1272 "build.h",
1273 "setup.h"
1274);
1275
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001276my %LocalIncludes = map {$_=>1} (
1277 "/usr/local/include",
1278 "/usr/local" );
1279
1280my %OS_AddPath=(
1281# These paths are needed if the tool cannot detect them automatically
1282 "macos"=>{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001283 "include"=>[
1284 "/Library",
1285 "/Developer/usr/include"
1286 ],
1287 "lib"=>[
1288 "/Library",
1289 "/Developer/usr/lib"
1290 ],
1291 "bin"=>[
1292 "/Developer/usr/bin"
1293 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001294 },
1295 "beos"=>{
1296 # Haiku has GCC 2.95.3 by default
1297 # try to find GCC>=3.0 in /boot/develop/abi
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001298 "include"=>[
1299 "/boot/common",
1300 "/boot/develop"
1301 ],
1302 "lib"=>[
1303 "/boot/common/lib",
1304 "/boot/system/lib",
1305 "/boot/apps"
1306 ],
1307 "bin"=>[
1308 "/boot/common/bin",
1309 "/boot/system/bin",
1310 "/boot/develop/abi"
1311 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001312 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001313);
1314
1315my %Slash_Type=(
1316 "default"=>"/",
1317 "windows"=>"\\"
1318);
1319
1320my $SLASH = $Slash_Type{$OSgroup}?$Slash_Type{$OSgroup}:$Slash_Type{"default"};
1321
1322# Global Variables
1323my %COMMON_LANGUAGE=(
1324 1 => "C",
1325 2 => "C" );
1326
1327my $MAX_COMMAND_LINE_ARGUMENTS = 4096;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001328my $MAX_CPPFILT_FILE_SIZE = 50000;
1329my $CPPFILT_SUPPORT_FILE;
1330
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001331my (%WORD_SIZE, %CPU_ARCH, %GCC_VERSION);
1332
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001333my $STDCXX_TESTING = 0;
1334my $GLIBC_TESTING = 0;
1335
1336my $CheckHeadersOnly = $CheckHeadersOnly_Opt;
1337my $CheckObjectsOnly = $CheckObjectsOnly_Opt;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001338my $TargetComponent;
1339
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001340my $CheckUndefined = 0;
1341
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001342# Set Target Component Name
1343if($TargetComponent_Opt) {
1344 $TargetComponent = lc($TargetComponent_Opt);
1345}
1346else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001347{ # default: library
1348 # other components: header, system, ...
1349 $TargetComponent = "library";
1350}
1351
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001352my $TOP_REF = "<a style='font-size:11px;' href='#Top'>to the top</a>";
1353
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001354my $SystemRoot;
1355
1356my $MAIN_CPP_DIR;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001357my %RESULT;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001358my %LOG_PATH;
1359my %DEBUG_PATH;
1360my %Cache;
1361my %LibInfo;
1362my $COMPILE_ERRORS = 0;
1363my %CompilerOptions;
1364my %CheckedDyLib;
1365my $TargetLibraryShortName = parse_libname($TargetLibraryName, "shortest", $OSgroup);
1366
1367# Constants (#defines)
1368my %Constants;
1369my %SkipConstants;
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04001370my %EnumConstants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001371
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001372# Extra Info
1373my %SymbolHeader;
1374my %KnownLibs;
1375
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001376# Types
1377my %TypeInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001378my %TemplateInstance;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04001379my %TemplateDecl;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001380my %SkipTypes = (
1381 "1"=>{},
1382 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001383my %CheckedTypes;
1384my %TName_Tid;
1385my %EnumMembName_Id;
1386my %NestedNameSpaces = (
1387 "1"=>{},
1388 "2"=>{} );
1389my %UsedType;
1390my %VirtualTable;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001391my %VirtualTable_Model;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001392my %ClassVTable;
1393my %ClassVTable_Content;
1394my %VTableClass;
1395my %AllocableClass;
1396my %ClassMethods;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001397my %ClassNames;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001398my %Class_SubClasses;
1399my %OverriddenMethods;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04001400my %TypedefToAnon;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001401my $MAX_ID = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001402
1403# Typedefs
1404my %Typedef_BaseName;
1405my %Typedef_Tr;
1406my %Typedef_Eq;
1407my %StdCxxTypedef;
1408my %MissedTypedef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001409my %MissedBase;
1410my %MissedBase_R;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001411my %TypeTypedef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001412
1413# Symbols
1414my %SymbolInfo;
1415my %tr_name;
1416my %mangled_name_gcc;
1417my %mangled_name;
1418my %SkipSymbols = (
1419 "1"=>{},
1420 "2"=>{} );
1421my %SkipNameSpaces = (
1422 "1"=>{},
1423 "2"=>{} );
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001424my %AddNameSpaces = (
1425 "1"=>{},
1426 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001427my %SymbolsList;
1428my %SymbolsList_App;
1429my %CheckedSymbols;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001430my %Symbol_Library = (
1431 "1"=>{},
1432 "2"=>{} );
1433my %Library_Symbol = (
1434 "1"=>{},
1435 "2"=>{} );
1436my %DepSymbol_Library = (
1437 "1"=>{},
1438 "2"=>{} );
1439my %DepLibrary_Symbol = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001440 "1"=>{},
1441 "2"=>{} );
1442my %MangledNames;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001443my %Func_ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001444my %AddIntParams;
1445my %Interface_Impl;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001446my %GlobalDataObject;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001447my %WeakSymbols;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001448
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001449# Extra Info
1450my %UndefinedSymbols;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001451my %PreprocessedHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001452
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001453# Headers
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001454my %Include_Preamble = (
1455 "1"=>[],
1456 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001457my %Registered_Headers;
1458my %HeaderName_Paths;
1459my %Header_Dependency;
1460my %Include_Neighbors;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001461my %Include_Paths = (
1462 "1"=>[],
1463 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001464my %INC_PATH_AUTODETECT = (
1465 "1"=>1,
1466 "2"=>1 );
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001467my %Add_Include_Paths = (
1468 "1"=>[],
1469 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001470my %Skip_Include_Paths;
1471my %RegisteredDirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001472my %Header_ErrorRedirect;
1473my %Header_Includes;
1474my %Header_ShouldNotBeUsed;
1475my %RecursiveIncludes;
1476my %Header_Include_Prefix;
1477my %SkipHeaders;
1478my %SkipHeadersList=(
1479 "1"=>{},
1480 "2"=>{} );
1481my %SkipLibs;
1482my %Include_Order;
1483my %TUnit_NameSpaces;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001484my %TUnit_Classes;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001485my %TUnit_Funcs;
1486my %TUnit_Vars;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001487
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001488my %CppMode = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001489 "1"=>0,
1490 "2"=>0 );
1491my %AutoPreambleMode = (
1492 "1"=>0,
1493 "2"=>0 );
1494my %MinGWMode = (
1495 "1"=>0,
1496 "2"=>0 );
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001497my %Cpp0xMode = (
1498 "1"=>0,
1499 "2"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001500
1501# Shared Objects
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001502my %RegisteredObjects;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001503my %RegisteredObjects_Short;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001504my %RegisteredSONAMEs;
1505my %RegisteredObject_Dirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001506
1507# System Objects
1508my %SystemObjects;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001509my @DefaultLibPaths;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001510my %DyLib_DefaultPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001511
1512# System Headers
1513my %SystemHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001514my @DefaultCppPaths;
1515my @DefaultGccPaths;
1516my @DefaultIncPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001517my %DefaultCppHeader;
1518my %DefaultGccHeader;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001519my @UsersIncPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001520
1521# Merging
1522my %CompleteSignature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001523my $Version;
1524my %AddedInt;
1525my %RemovedInt;
1526my %AddedInt_Virt;
1527my %RemovedInt_Virt;
1528my %VirtualReplacement;
1529my %ChangedTypedef;
1530my %CompatRules;
1531my %IncompleteRules;
1532my %UnknownRules;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001533my %VTableChanged_M;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001534my %ExtendedSymbols;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001535my %ReturnedClass;
1536my %ParamClass;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001537my %SourceAlternative;
1538my %SourceAlternative_B;
1539my %SourceReplacement;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001540
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001541# Calling Conventions
1542my %UseConv_Real = (
1543 "1"=>0,
1544 "2"=>0 );
1545
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001546# OS Compliance
1547my %TargetLibs;
1548my %TargetHeaders;
1549
1550# OS Specifics
1551my $OStarget = $OSgroup;
1552my %TargetTools;
1553
1554# Compliance Report
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001555my %Type_MaxSeverity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001556
1557# Recursion locks
1558my @RecurLib;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001559my @RecurTypes;
1560my @RecurInclude;
1561my @RecurConstant;
1562
1563# System
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001564my %SystemPaths = (
1565 "include"=>[],
1566 "lib"=>[],
1567 "bin"=>[]
1568);
1569my @DefaultBinPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001570my $GCC_PATH;
1571
1572# Symbols versioning
1573my %SymVer = (
1574 "1"=>{},
1575 "2"=>{} );
1576
1577# Problem descriptions
1578my %CompatProblems;
1579my %ProblemsWithConstants;
1580my %ImplProblems;
1581my %TotalAffected;
1582
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001583# Reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001584my $ContentID = 1;
1585my $ContentSpanStart = "<span class=\"section\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1586my $ContentSpanStart_Affected = "<span class=\"section_affected\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1587my $ContentSpanStart_Info = "<span class=\"section_info\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1588my $ContentSpanEnd = "</span>\n";
1589my $ContentDivStart = "<div id=\"CONTENT_ID\" style=\"display:none;\">\n";
1590my $ContentDivEnd = "</div>\n";
1591my $Content_Counter = 0;
1592
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001593# Modes
1594my $JoinReport = 1;
1595my $DoubleReport = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001596
1597sub get_Modules()
1598{
1599 my $TOOL_DIR = get_dirname($0);
1600 if(not $TOOL_DIR)
1601 { # patch for MS Windows
1602 $TOOL_DIR = ".";
1603 }
1604 my @SEARCH_DIRS = (
1605 # tool's directory
1606 abs_path($TOOL_DIR),
1607 # relative path to modules
1608 abs_path($TOOL_DIR)."/../share/abi-compliance-checker",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001609 # install path
1610 'MODULES_INSTALL_PATH'
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001611 );
1612 foreach my $DIR (@SEARCH_DIRS)
1613 {
1614 if(not is_abs($DIR))
1615 { # relative path
1616 $DIR = abs_path($TOOL_DIR)."/".$DIR;
1617 }
1618 if(-d $DIR."/modules") {
1619 return $DIR."/modules";
1620 }
1621 }
1622 exitStatus("Module_Error", "can't find modules");
1623}
1624
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001625my %LoadedModules = ();
1626
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001627sub loadModule($)
1628{
1629 my $Name = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001630 if(defined $LoadedModules{$Name}) {
1631 return;
1632 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001633 my $Path = $MODULES_DIR."/Internals/$Name.pm";
1634 if(not -f $Path) {
1635 exitStatus("Module_Error", "can't access \'$Path\'");
1636 }
1637 require $Path;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001638 $LoadedModules{$Name} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001639}
1640
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001641sub readModule($$)
1642{
1643 my ($Module, $Name) = @_;
1644 my $Path = $MODULES_DIR."/Internals/$Module/".$Name;
1645 if(not -f $Path) {
1646 exitStatus("Module_Error", "can't access \'$Path\'");
1647 }
1648 return readFile($Path);
1649}
1650
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04001651sub showPos($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001652{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001653 my $Number = $_[0];
1654 if(not $Number) {
1655 $Number = 1;
1656 }
1657 else {
1658 $Number = int($Number)+1;
1659 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001660 if($Number>3) {
1661 return $Number."th";
1662 }
1663 elsif($Number==1) {
1664 return "1st";
1665 }
1666 elsif($Number==2) {
1667 return "2nd";
1668 }
1669 elsif($Number==3) {
1670 return "3rd";
1671 }
1672 else {
1673 return $Number;
1674 }
1675}
1676
1677sub search_Tools($)
1678{
1679 my $Name = $_[0];
1680 return "" if(not $Name);
1681 if(my @Paths = keys(%TargetTools))
1682 {
1683 foreach my $Path (@Paths)
1684 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001685 if(-f join_P($Path, $Name)) {
1686 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001687 }
1688 if($CrossPrefix)
1689 { # user-defined prefix (arm-none-symbianelf, ...)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001690 my $Candidate = join_P($Path, $CrossPrefix."-".$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001691 if(-f $Candidate) {
1692 return $Candidate;
1693 }
1694 }
1695 }
1696 }
1697 else {
1698 return "";
1699 }
1700}
1701
1702sub synch_Cmd($)
1703{
1704 my $Name = $_[0];
1705 if(not $GCC_PATH)
1706 { # GCC was not found yet
1707 return "";
1708 }
1709 my $Candidate = $GCC_PATH;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001710 if($Candidate=~s/\bgcc(|\.\w+)\Z/$Name$1/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001711 return $Candidate;
1712 }
1713 return "";
1714}
1715
1716sub get_CmdPath($)
1717{
1718 my $Name = $_[0];
1719 return "" if(not $Name);
1720 if(defined $Cache{"get_CmdPath"}{$Name}) {
1721 return $Cache{"get_CmdPath"}{$Name};
1722 }
1723 my %BinUtils = map {$_=>1} (
1724 "c++filt",
1725 "objdump",
1726 "readelf"
1727 );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001728 if($BinUtils{$Name} and $GCC_PATH)
1729 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001730 if(my $Dir = get_dirname($GCC_PATH)) {
1731 $TargetTools{$Dir}=1;
1732 }
1733 }
1734 my $Path = search_Tools($Name);
1735 if(not $Path and $OSgroup eq "windows") {
1736 $Path = search_Tools($Name.".exe");
1737 }
1738 if(not $Path and $BinUtils{$Name})
1739 {
1740 if($CrossPrefix)
1741 { # user-defined prefix
1742 $Path = search_Cmd($CrossPrefix."-".$Name);
1743 }
1744 }
1745 if(not $Path and $BinUtils{$Name})
1746 {
1747 if(my $Candidate = synch_Cmd($Name))
1748 { # synch with GCC
1749 if($Candidate=~/[\/\\]/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001750 { # command path
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001751 if(-f $Candidate) {
1752 $Path = $Candidate;
1753 }
1754 }
1755 elsif($Candidate = search_Cmd($Candidate))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001756 { # command name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001757 $Path = $Candidate;
1758 }
1759 }
1760 }
1761 if(not $Path) {
1762 $Path = search_Cmd($Name);
1763 }
1764 if(not $Path and $OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001765 { # search for *.exe file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001766 $Path=search_Cmd($Name.".exe");
1767 }
1768 if($Path=~/\s/) {
1769 $Path = "\"".$Path."\"";
1770 }
1771 return ($Cache{"get_CmdPath"}{$Name}=$Path);
1772}
1773
1774sub search_Cmd($)
1775{
1776 my $Name = $_[0];
1777 return "" if(not $Name);
1778 if(defined $Cache{"search_Cmd"}{$Name}) {
1779 return $Cache{"search_Cmd"}{$Name};
1780 }
1781 if(my $DefaultPath = get_CmdPath_Default($Name)) {
1782 return ($Cache{"search_Cmd"}{$Name} = $DefaultPath);
1783 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001784 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001785 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001786 my $CmdPath = join_P($Path,$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001787 if(-f $CmdPath)
1788 {
1789 if($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001790 next if(not check_gcc($CmdPath, "3"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001791 }
1792 return ($Cache{"search_Cmd"}{$Name} = $CmdPath);
1793 }
1794 }
1795 return ($Cache{"search_Cmd"}{$Name} = "");
1796}
1797
1798sub get_CmdPath_Default($)
1799{ # search in PATH
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001800 return "" if(not $_[0]);
1801 if(defined $Cache{"get_CmdPath_Default"}{$_[0]}) {
1802 return $Cache{"get_CmdPath_Default"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001803 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001804 return ($Cache{"get_CmdPath_Default"}{$_[0]} = get_CmdPath_Default_I($_[0]));
1805}
1806
1807sub get_CmdPath_Default_I($)
1808{ # search in PATH
1809 my $Name = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001810 if($Name=~/find/)
1811 { # special case: search for "find" utility
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001812 if(`find \"$TMP_DIR\" -maxdepth 0 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001813 return "find";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001814 }
1815 }
1816 elsif($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001817 return check_gcc($Name, "3");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001818 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001819 if(checkCmd($Name)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001820 return $Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001821 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001822 if($OSgroup eq "windows")
1823 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001824 if(`$Name /? 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001825 return $Name;
1826 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001827 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001828 foreach my $Path (@DefaultBinPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001829 {
1830 if(-f $Path."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001831 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001832 }
1833 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001834 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001835}
1836
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001837sub classifyPath($)
1838{
1839 my $Path = $_[0];
1840 if($Path=~/[\*\[]/)
1841 { # wildcard
1842 $Path=~s/\*/.*/g;
1843 $Path=~s/\\/\\\\/g;
1844 return ($Path, "Pattern");
1845 }
1846 elsif($Path=~/[\/\\]/)
1847 { # directory or relative path
1848 return (path_format($Path, $OSgroup), "Path");
1849 }
1850 else {
1851 return ($Path, "Name");
1852 }
1853}
1854
1855sub readDescriptor($$)
1856{
1857 my ($LibVersion, $Content) = @_;
1858 return if(not $LibVersion);
1859 my $DName = $DumpAPI?"descriptor":"descriptor \"d$LibVersion\"";
1860 if(not $Content) {
1861 exitStatus("Error", "$DName is empty");
1862 }
1863 if($Content!~/\</) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04001864 exitStatus("Error", "incorrect descriptor (see -d1 option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001865 }
1866 $Content=~s/\/\*(.|\n)+?\*\///g;
1867 $Content=~s/<\!--(.|\n)+?-->//g;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001868
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001869 $Descriptor{$LibVersion}{"Version"} = parseTag(\$Content, "version");
1870 if($TargetVersion{$LibVersion}) {
1871 $Descriptor{$LibVersion}{"Version"} = $TargetVersion{$LibVersion};
1872 }
1873 if(not $Descriptor{$LibVersion}{"Version"}) {
1874 exitStatus("Error", "version in the $DName is not specified (<version> section)");
1875 }
1876 if($Content=~/{RELPATH}/)
1877 {
1878 if(my $RelDir = $RelativeDirectory{$LibVersion}) {
1879 $Content =~ s/{RELPATH}/$RelDir/g;
1880 }
1881 else
1882 {
1883 my $NeedRelpath = $DumpAPI?"-relpath":"-relpath$LibVersion";
1884 exitStatus("Error", "you have not specified $NeedRelpath option, but the $DName contains {RELPATH} macro");
1885 }
1886 }
1887
1888 if(not $CheckObjectsOnly_Opt)
1889 {
1890 my $DHeaders = parseTag(\$Content, "headers");
1891 if(not $DHeaders) {
1892 exitStatus("Error", "header files in the $DName are not specified (<headers> section)");
1893 }
1894 elsif(lc($DHeaders) ne "none")
1895 { # append the descriptor headers list
1896 if($Descriptor{$LibVersion}{"Headers"})
1897 { # multiple descriptors
1898 $Descriptor{$LibVersion}{"Headers"} .= "\n".$DHeaders;
1899 }
1900 else {
1901 $Descriptor{$LibVersion}{"Headers"} = $DHeaders;
1902 }
1903 foreach my $Path (split(/\s*\n\s*/, $DHeaders))
1904 {
1905 if(not -e $Path) {
1906 exitStatus("Access_Error", "can't access \'$Path\'");
1907 }
1908 }
1909 }
1910 }
1911 if(not $CheckHeadersOnly_Opt)
1912 {
1913 my $DObjects = parseTag(\$Content, "libs");
1914 if(not $DObjects) {
1915 exitStatus("Error", "$SLIB_TYPE libraries in the $DName are not specified (<libs> section)");
1916 }
1917 elsif(lc($DObjects) ne "none")
1918 { # append the descriptor libraries list
1919 if($Descriptor{$LibVersion}{"Libs"})
1920 { # multiple descriptors
1921 $Descriptor{$LibVersion}{"Libs"} .= "\n".$DObjects;
1922 }
1923 else {
1924 $Descriptor{$LibVersion}{"Libs"} .= $DObjects;
1925 }
1926 foreach my $Path (split(/\s*\n\s*/, $DObjects))
1927 {
1928 if(not -e $Path) {
1929 exitStatus("Access_Error", "can't access \'$Path\'");
1930 }
1931 }
1932 }
1933 }
1934 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers")))
1935 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001936 if(not -d $Path) {
1937 exitStatus("Access_Error", "can't access directory \'$Path\'");
1938 }
1939 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001940 push_U($SystemPaths{"include"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001941 }
1942 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs")))
1943 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001944 if(not -d $Path) {
1945 exitStatus("Access_Error", "can't access directory \'$Path\'");
1946 }
1947 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001948 push_U($SystemPaths{"lib"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001949 }
1950 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools")))
1951 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001952 if(not -d $Path) {
1953 exitStatus("Access_Error", "can't access directory \'$Path\'");
1954 }
1955 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001956 push_U($SystemPaths{"bin"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001957 $TargetTools{$Path}=1;
1958 }
1959 if(my $Prefix = parseTag(\$Content, "cross_prefix")) {
1960 $CrossPrefix = $Prefix;
1961 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001962 $Descriptor{$LibVersion}{"IncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"IncludePaths"}); # perl 5.8 doesn't support //=
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001963 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "include_paths")))
1964 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001965 if(not -d $Path) {
1966 exitStatus("Access_Error", "can't access directory \'$Path\'");
1967 }
1968 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001969 push(@{$Descriptor{$LibVersion}{"IncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001970 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001971 $Descriptor{$LibVersion}{"AddIncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"AddIncludePaths"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001972 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "add_include_paths")))
1973 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001974 if(not -d $Path) {
1975 exitStatus("Access_Error", "can't access directory \'$Path\'");
1976 }
1977 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001978 push(@{$Descriptor{$LibVersion}{"AddIncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001979 }
1980 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_include_paths")))
1981 {
1982 # skip some auto-generated include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001983 $Skip_Include_Paths{$LibVersion}{path_format($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001984 }
1985 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_including")))
1986 {
1987 # skip direct including of some headers
1988 my ($CPath, $Type) = classifyPath($Path);
1989 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001990 }
1991 $Descriptor{$LibVersion}{"GccOptions"} = parseTag(\$Content, "gcc_options");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001992 foreach my $Option (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"GccOptions"}))
1993 {
1994 if(index($Option, "-Wl")==-1) {
1995 $CompilerOptions{$LibVersion} .= " ".$Option;
1996 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001997 }
1998 $Descriptor{$LibVersion}{"SkipHeaders"} = parseTag(\$Content, "skip_headers");
1999 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipHeaders"}))
2000 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002001 $SkipHeadersList{$LibVersion}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002002 my ($CPath, $Type) = classifyPath($Path);
2003 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002004 }
2005 $Descriptor{$LibVersion}{"SkipLibs"} = parseTag(\$Content, "skip_libs");
2006 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipLibs"}))
2007 {
2008 my ($CPath, $Type) = classifyPath($Path);
2009 $SkipLibs{$LibVersion}{$Type}{$CPath} = 1;
2010 }
2011 if(my $DDefines = parseTag(\$Content, "defines"))
2012 {
2013 if($Descriptor{$LibVersion}{"Defines"})
2014 { # multiple descriptors
2015 $Descriptor{$LibVersion}{"Defines"} .= "\n".$DDefines;
2016 }
2017 else {
2018 $Descriptor{$LibVersion}{"Defines"} = $DDefines;
2019 }
2020 }
2021 foreach my $Order (split(/\s*\n\s*/, parseTag(\$Content, "include_order")))
2022 {
2023 if($Order=~/\A(.+):(.+)\Z/) {
2024 $Include_Order{$LibVersion}{$1} = $2;
2025 }
2026 }
2027 foreach my $Type_Name (split(/\s*\n\s*/, parseTag(\$Content, "opaque_types")),
2028 split(/\s*\n\s*/, parseTag(\$Content, "skip_types")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002029 { # opaque_types renamed to skip_types (1.23.4)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002030 $SkipTypes{$LibVersion}{$Type_Name} = 1;
2031 }
2032 foreach my $Symbol (split(/\s*\n\s*/, parseTag(\$Content, "skip_interfaces")),
2033 split(/\s*\n\s*/, parseTag(\$Content, "skip_symbols")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002034 { # skip_interfaces renamed to skip_symbols (1.22.1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002035 $SkipSymbols{$LibVersion}{$Symbol} = 1;
2036 }
2037 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "skip_namespaces"))) {
2038 $SkipNameSpaces{$LibVersion}{$NameSpace} = 1;
2039 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04002040 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "add_namespaces"))) {
2041 $AddNameSpaces{$LibVersion}{$NameSpace} = 1;
2042 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002043 foreach my $Constant (split(/\s*\n\s*/, parseTag(\$Content, "skip_constants"))) {
2044 $SkipConstants{$LibVersion}{$Constant} = 1;
2045 }
2046 if(my $DIncPreamble = parseTag(\$Content, "include_preamble"))
2047 {
2048 if($Descriptor{$LibVersion}{"IncludePreamble"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002049 { # multiple descriptors
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002050 $Descriptor{$LibVersion}{"IncludePreamble"} .= "\n".$DIncPreamble;
2051 }
2052 else {
2053 $Descriptor{$LibVersion}{"IncludePreamble"} = $DIncPreamble;
2054 }
2055 }
2056}
2057
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002058sub parseTag(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002059{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002060 my $CodeRef = shift(@_);
2061 my $Tag = shift(@_);
2062 if(not $Tag or not $CodeRef) {
2063 return undef;
2064 }
2065 my $Sp = 0;
2066 if(@_) {
2067 $Sp = shift(@_);
2068 }
2069 my $Start = index(${$CodeRef}, "<$Tag>");
2070 if($Start!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002071 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002072 my $End = index(${$CodeRef}, "</$Tag>");
2073 if($End!=-1)
2074 {
2075 my $TS = length($Tag)+3;
2076 my $Content = substr(${$CodeRef}, $Start, $End-$Start+$TS, "");
2077 substr($Content, 0, $TS-1, ""); # cut start tag
2078 substr($Content, -$TS, $TS, ""); # cut end tag
2079 if(not $Sp)
2080 {
2081 $Content=~s/\A\s+//g;
2082 $Content=~s/\s+\Z//g;
2083 }
2084 if(substr($Content, 0, 1) ne "<") {
2085 $Content = xmlSpecChars_R($Content);
2086 }
2087 return $Content;
2088 }
2089 }
2090 return undef;
2091}
2092
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002093sub getInfo($)
2094{
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002095 my $DumpPath = $_[0];
2096 return if(not $DumpPath or not -f $DumpPath);
2097
2098 readTUDump($DumpPath);
2099
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002100 # processing info
2101 setTemplateParams_All();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002102
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002103 if($ExtraDump) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002104 setAnonTypedef_All();
2105 }
2106
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002107 getTypeInfo_All();
2108 simplifyNames();
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002109 simplifyConstants();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002110 getVarInfo_All();
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002111 getSymbolInfo_All();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002112
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002113
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002114 # clean memory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002115 %LibInfo = ();
2116 %TemplateInstance = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002117 %MangledNames = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002118 %TemplateDecl = ();
2119 %StdCxxTypedef = ();
2120 %MissedTypedef = ();
2121 %Typedef_Tr = ();
2122 %Typedef_Eq = ();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002123 %TypedefToAnon = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002124
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002125 # clean cache
2126 delete($Cache{"getTypeAttr"});
2127 delete($Cache{"getTypeDeclId"});
2128
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002129 if($ExtraDump)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002130 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002131 foreach (keys(%{$TypeInfo{$Version}}))
2132 {
2133 if($TypeInfo{$Version}{$_}{"Artificial"}) {
2134 delete($TypeInfo{$Version}{$_});
2135 }
2136 }
2137 }
2138 else
2139 { # remove unused types
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002140 if($BinaryOnly and not $ExtendedCheck)
2141 { # --binary
2142 removeUnused($Version, "All");
2143 }
2144 else {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002145 removeUnused($Version, "Extended");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002146 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002147 }
2148
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002149 if($Debug) {
2150 # debugMangling($Version);
2151 }
2152}
2153
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002154sub readTUDump($)
2155{
2156 my $DumpPath = $_[0];
2157
2158 open(TU_DUMP, $DumpPath);
2159 local $/ = undef;
2160 my $Content = <TU_DUMP>;
2161 close(TU_DUMP);
2162
2163 unlink($DumpPath);
2164
2165 $Content=~s/\n[ ]+/ /g;
2166 my @Lines = split("\n", $Content);
2167
2168 # clean memory
2169 undef $Content;
2170
2171 $MAX_ID = $#Lines+1;
2172
2173 foreach (0 .. $#Lines)
2174 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002175 if($Lines[$_]=~/\A\@(\d+)[ ]+([a-z_]+)[ ]+(.+)\Z/i)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002176 { # get a number and attributes of a node
2177 next if(not $NodeType{$2});
2178 $LibInfo{$Version}{"info_type"}{$1}=$2;
2179 $LibInfo{$Version}{"info"}{$1}=$3;
2180 }
2181
2182 # clean memory
2183 delete($Lines[$_]);
2184 }
2185
2186 # clean memory
2187 undef @Lines;
2188}
2189
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002190sub simplifyConstants()
2191{
2192 foreach my $Constant (keys(%{$Constants{$Version}}))
2193 {
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04002194 my $Value = $Constants{$Version}{$Constant}{"Value"};
2195 if(defined $EnumConstants{$Version}{$Value}) {
2196 $Constants{$Version}{$Constant}{"Value"} = $EnumConstants{$Version}{$Constant}{"Value"};
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002197 }
2198 }
2199}
2200
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002201sub simplifyNames()
2202{
2203 foreach my $Base (keys(%{$Typedef_Tr{$Version}}))
2204 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002205 if($Typedef_Eq{$Version}{$Base}) {
2206 next;
2207 }
2208 my @Translations = sort keys(%{$Typedef_Tr{$Version}{$Base}});
2209 if($#Translations==0)
2210 {
2211 if(length($Translations[0])<=length($Base)) {
2212 $Typedef_Eq{$Version}{$Base} = $Translations[0];
2213 }
2214 }
2215 else
2216 { # select most appropriate
2217 foreach my $Tr (@Translations)
2218 {
2219 if($Base=~/\A\Q$Tr\E/)
2220 {
2221 $Typedef_Eq{$Version}{$Base} = $Tr;
2222 last;
2223 }
2224 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002225 }
2226 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002227 foreach my $TypeId (keys(%{$TypeInfo{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002228 {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002229 my $TypeName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002230 if(not $TypeName) {
2231 next;
2232 }
2233 next if(index($TypeName,"<")==-1);# template instances only
2234 if($TypeName=~/>(::\w+)+\Z/)
2235 { # skip unused types
2236 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002237 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002238 foreach my $Base (sort {length($b)<=>length($a)}
2239 sort {$b cmp $a} keys(%{$Typedef_Eq{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002240 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002241 next if(not $Base);
2242 next if(index($TypeName,$Base)==-1);
2243 next if(length($TypeName) - length($Base) <= 3);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002244 if(my $Typedef = $Typedef_Eq{$Version}{$Base})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002245 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002246 $TypeName=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g;
2247 $TypeName=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g;
2248 if(defined $TypeInfo{$Version}{$TypeId}{"TParam"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002249 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002250 foreach my $TPos (keys(%{$TypeInfo{$Version}{$TypeId}{"TParam"}}))
2251 {
2252 if(my $TPName = $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"})
2253 {
2254 $TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g;
2255 $TPName=~s/\A\Q$Base\E(\w|\Z)/$Typedef $1/g;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002256 $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName, "T");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002257 }
2258 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002259 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002260 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002261 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002262 $TypeName = formatName($TypeName, "T");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002263 $TypeInfo{$Version}{$TypeId}{"Name"} = $TypeName;
2264 $TName_Tid{$Version}{$TypeName} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002265 }
2266}
2267
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002268sub setAnonTypedef_All()
2269{
2270 foreach my $InfoId (keys(%{$LibInfo{$Version}{"info"}}))
2271 {
2272 if($LibInfo{$Version}{"info_type"}{$InfoId} eq "type_decl")
2273 {
2274 if(isAnon(getNameByInfo($InfoId))) {
2275 $TypedefToAnon{getTypeId($InfoId)} = 1;
2276 }
2277 }
2278 }
2279}
2280
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002281sub setTemplateParams_All()
2282{
2283 foreach (keys(%{$LibInfo{$Version}{"info"}}))
2284 {
2285 if($LibInfo{$Version}{"info_type"}{$_} eq "template_decl") {
2286 setTemplateParams($_);
2287 }
2288 }
2289}
2290
2291sub setTemplateParams($)
2292{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002293 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002294 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002295 if($Info=~/(inst|spcs)[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002296 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002297 my $TmplInst_Id = $2;
2298 setTemplateInstParams($TmplInst_Id);
2299 while($TmplInst_Id = getNextElem($TmplInst_Id)) {
2300 setTemplateInstParams($TmplInst_Id);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002301 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002302 }
2303 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002304 if(my $TypeId = getTreeAttr_Type($_[0]))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002305 {
2306 if(my $IType = $LibInfo{$Version}{"info_type"}{$TypeId})
2307 {
2308 if($IType eq "record_type") {
2309 $TemplateDecl{$Version}{$TypeId}=1;
2310 }
2311 }
2312 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002313}
2314
2315sub setTemplateInstParams($)
2316{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002317 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002318 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002319 my ($Params_InfoId, $ElemId) = ();
2320 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
2321 $Params_InfoId = $1;
2322 }
2323 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
2324 $ElemId = $1;
2325 }
2326 if($Params_InfoId and $ElemId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002327 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002328 my $Params_Info = $LibInfo{$Version}{"info"}{$Params_InfoId};
2329 while($Params_Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
2330 {
2331 my ($PPos, $PTypeId) = ($1, $2);
2332 if(my $PType = $LibInfo{$Version}{"info_type"}{$PTypeId})
2333 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002334 if($PType eq "template_type_parm")
2335 {
2336 $TemplateDecl{$Version}{$ElemId}=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002337 return;
2338 }
2339 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002340 if($LibInfo{$Version}{"info_type"}{$ElemId} eq "function_decl")
2341 { # functions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002342 $TemplateInstance{$Version}{"Func"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002343 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002344 else
2345 { # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002346 $TemplateInstance{$Version}{"Type"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002347 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002348 }
2349 }
2350 }
2351}
2352
2353sub getTypeDeclId($)
2354{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002355 if($_[0])
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002356 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002357 if(defined $Cache{"getTypeDeclId"}{$Version}{$_[0]}) {
2358 return $Cache{"getTypeDeclId"}{$Version}{$_[0]};
2359 }
2360 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2361 {
2362 if($Info=~/name[ ]*:[ ]*@(\d+)/) {
2363 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = $1);
2364 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002365 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002366 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002367 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002368}
2369
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002370sub getTypeInfo_All()
2371{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002372 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002373 { # support for GCC < 4.5
2374 # missed typedefs: QStyle::State is typedef to QFlags<QStyle::StateFlag>
2375 # but QStyleOption.state is of type QFlags<QStyle::StateFlag> in the TU dump
2376 # FIXME: check GCC versions
2377 addMissedTypes_Pre();
2378 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002379
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002380 foreach (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002381 { # forward order only
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002382 my $IType = $LibInfo{$Version}{"info_type"}{$_};
2383 if($IType=~/_type\Z/ and $IType ne "function_type"
2384 and $IType ne "method_type") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002385 getTypeInfo("$_");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002386 }
2387 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002388
2389 # add "..." type
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002390 $TypeInfo{$Version}{"-1"} = {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002391 "Name" => "...",
2392 "Type" => "Intrinsic",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002393 "Tid" => "-1"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002394 };
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002395 $TName_Tid{$Version}{"..."} = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002396
2397 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002398 { # support for GCC < 4.5
2399 addMissedTypes_Post();
2400 }
2401}
2402
2403sub addMissedTypes_Pre()
2404{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002405 my %MissedTypes = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002406 foreach my $MissedTDid (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
2407 { # detecting missed typedefs
2408 if($LibInfo{$Version}{"info_type"}{$MissedTDid} eq "type_decl")
2409 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002410 my $TypeId = getTreeAttr_Type($MissedTDid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002411 next if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002412 my $TypeType = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002413 if($TypeType eq "Unknown")
2414 { # template_type_parm
2415 next;
2416 }
2417 my $TypeDeclId = getTypeDeclId($TypeId);
2418 next if($TypeDeclId eq $MissedTDid);#or not $TypeDeclId
2419 my $TypedefName = getNameByInfo($MissedTDid);
2420 next if(not $TypedefName);
2421 next if($TypedefName eq "__float80");
2422 next if(isAnon($TypedefName));
2423 if(not $TypeDeclId
2424 or getNameByInfo($TypeDeclId) ne $TypedefName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002425 $MissedTypes{$Version}{$TypeId}{$MissedTDid} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002426 }
2427 }
2428 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002429 my %AddTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002430 foreach my $Tid (keys(%{$MissedTypes{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002431 { # add missed typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002432 my @Missed = keys(%{$MissedTypes{$Version}{$Tid}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002433 if(not @Missed or $#Missed>=1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002434 next;
2435 }
2436 my $MissedTDid = $Missed[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002437 my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002438 if(not $TypedefName) {
2439 next;
2440 }
2441 $MAX_ID++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002442 my %MissedInfo = ( # typedef info
2443 "Name" => $TypedefName,
2444 "NameSpace" => $TypedefNS,
2445 "BaseType" => {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002446 "Tid" => $Tid
2447 },
2448 "Type" => "Typedef",
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002449 "Tid" => "$MAX_ID" );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002450 my ($H, $L) = getLocation($MissedTDid);
2451 $MissedInfo{"Header"} = $H;
2452 $MissedInfo{"Line"} = $L;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002453 if($TypedefName=~/\*|\&|\s/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002454 { # other types
2455 next;
2456 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002457 if($TypedefName=~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002458 { # QFlags<Qt::DropAction>::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002459 next;
2460 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002461 if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002462 { # double-check for the name of typedef
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002463 my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002464 next if(not $TName);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002465 if(length($TypedefName)>=length($TName))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002466 { # too long typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002467 next;
2468 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002469 if($TName=~/\A\Q$TypedefName\E</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002470 next;
2471 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002472 if($TypedefName=~/\A\Q$TName\E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002473 { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002474 next;
2475 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002476 if(get_depth($TypedefName)==0 and get_depth($TName)!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002477 { # std::_Vector_base and std::vector::_Base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002478 next;
2479 }
2480 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002481
2482 $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo;
2483
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002484 # register typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002485 $MissedTypedef{$Version}{$Tid}{"Tid"} = $MissedInfo{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002486 $MissedTypedef{$Version}{$Tid}{"TDid"} = $MissedTDid;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002487 $TName_Tid{$Version}{$TypedefName} = $MissedInfo{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002488 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002489
2490 # add missed & remove other
2491 $TypeInfo{$Version} = \%AddTypes;
2492 delete($Cache{"getTypeAttr"}{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002493}
2494
2495sub addMissedTypes_Post()
2496{
2497 foreach my $BaseId (keys(%{$MissedTypedef{$Version}}))
2498 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002499 if(my $Tid = $MissedTypedef{$Version}{$BaseId}{"Tid"})
2500 {
2501 $TypeInfo{$Version}{$Tid}{"Size"} = $TypeInfo{$Version}{$BaseId}{"Size"};
2502 if(my $TName = $TypeInfo{$Version}{$Tid}{"Name"}) {
2503 $Typedef_BaseName{$Version}{$TName} = $TypeInfo{$Version}{$BaseId}{"Name"};
2504 }
2505 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002506 }
2507}
2508
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002509sub getTypeInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002510{
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002511 my $TypeId = $_[0];
2512 %{$TypeInfo{$Version}{$TypeId}} = getTypeAttr($TypeId);
2513 my $TName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002514 if(not $TName) {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002515 delete($TypeInfo{$Version}{$TypeId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002516 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002517}
2518
2519sub getArraySize($$)
2520{
2521 my ($TypeId, $BaseName) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002522 if(my $Size = getSize($TypeId))
2523 {
2524 my $Elems = $Size/$BYTE_SIZE;
2525 while($BaseName=~s/\s*\[(\d+)\]//) {
2526 $Elems/=$1;
2527 }
2528 if(my $BasicId = $TName_Tid{$Version}{$BaseName})
2529 {
2530 if(my $BasicSize = $TypeInfo{$Version}{$BasicId}{"Size"}) {
2531 $Elems/=$BasicSize;
2532 }
2533 }
2534 return $Elems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002535 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002536 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002537}
2538
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002539sub getTParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002540{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002541 my ($TypeId, $Kind) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002542 my @TmplParams = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002543 my @Positions = sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$Kind}{$TypeId}});
2544 foreach my $Pos (@Positions)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002545 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002546 my $Param_TypeId = $TemplateInstance{$Version}{$Kind}{$TypeId}{$Pos};
2547 my $NodeType = $LibInfo{$Version}{"info_type"}{$Param_TypeId};
2548 if(not $NodeType)
2549 { # typename_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002550 return ();
2551 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002552 if($NodeType eq "tree_vec")
2553 {
2554 if($Pos!=$#Positions)
2555 { # select last vector of parameters ( ns<P1>::type<P2> )
2556 next;
2557 }
2558 }
2559 my @Params = get_TemplateParam($Pos, $Param_TypeId);
2560 foreach my $P (@Params)
2561 {
2562 if($P eq "") {
2563 return ();
2564 }
2565 elsif($P ne "\@skip\@") {
2566 @TmplParams = (@TmplParams, $P);
2567 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002568 }
2569 }
2570 return @TmplParams;
2571}
2572
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002573sub getTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002574{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002575 my $TypeId = $_[0];
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002576 my %TypeAttr = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002577 if(defined $TypeInfo{$Version}{$TypeId}
2578 and $TypeInfo{$Version}{$TypeId}{"Name"})
2579 { # already created
2580 return %{$TypeInfo{$Version}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002581 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002582 elsif($Cache{"getTypeAttr"}{$Version}{$TypeId})
2583 { # incomplete type
2584 return ();
2585 }
2586 $Cache{"getTypeAttr"}{$Version}{$TypeId} = 1;
2587
2588 my $TypeDeclId = getTypeDeclId($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002589 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002590
2591 if(not $MissedBase{$Version}{$TypeId} and isTypedef($TypeId))
2592 {
2593 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
2594 {
2595 if($Info=~/qual[ ]*:/)
2596 {
2597 if(my $NID = ++$MAX_ID)
2598 {
2599 $MissedBase{$Version}{$TypeId}="$NID";
2600 $MissedBase_R{$Version}{$NID}=$TypeId;
2601 $LibInfo{$Version}{"info"}{$NID} = $LibInfo{$Version}{"info"}{$TypeId};
2602 $LibInfo{$Version}{"info_type"}{$NID} = $LibInfo{$Version}{"info_type"}{$TypeId};
2603 }
2604 }
2605 }
2606 $TypeAttr{"Type"} = "Typedef";
2607 }
2608 else {
2609 $TypeAttr{"Type"} = getTypeType($TypeId);
2610 }
2611
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002612 if($TypeAttr{"Type"} eq "Unknown") {
2613 return ();
2614 }
2615 elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/)
2616 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002617 %TypeAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"});
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002618 if(my $TName = $TypeAttr{"Name"})
2619 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002620 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002621 $TName_Tid{$Version}{$TName} = $TypeId;
2622 return %TypeAttr;
2623 }
2624 else {
2625 return ();
2626 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002627 }
2628 elsif($TypeAttr{"Type"} eq "Array")
2629 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002630 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2631 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002632 return ();
2633 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002634 if(my $Algn = getAlgn($TypeId)) {
2635 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2636 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002637 $TypeAttr{"BaseType"}{"Tid"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002638 if(my %BTAttr = getTypeAttr($BTid))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002639 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002640 if(not $BTAttr{"Name"}) {
2641 return ();
2642 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002643 if(my $NElems = getArraySize($TypeId, $BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002644 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002645 if(my $Size = getSize($TypeId)) {
2646 $TypeAttr{"Size"} = $Size/$BYTE_SIZE;
2647 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002648 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002649 $TypeAttr{"Name"} = $1."[$NElems]".$2;
2650 }
2651 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002652 $TypeAttr{"Name"} = $BTAttr{"Name"}."[$NElems]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002653 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002654 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002655 else
2656 {
2657 $TypeAttr{"Size"} = $WORD_SIZE{$Version}; # pointer
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002658 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002659 $TypeAttr{"Name"} = $1."[]".$2;
2660 }
2661 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002662 $TypeAttr{"Name"} = $BTAttr{"Name"}."[]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002663 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002664 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002665 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002666 if($BTAttr{"Header"}) {
2667 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002668 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002669 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002670 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2671 return %TypeAttr;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002672 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002673 return ();
2674 }
2675 elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
2676 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002677 %TypeAttr = getTrivialTypeAttr($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002678 if($TypeAttr{"Name"})
2679 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002680 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2681 if($TypeAttr{"Name"} ne "int" or getTypeDeclId($TypeAttr{"Tid"}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002682 { # NOTE: register only one int: with built-in decl
2683 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2684 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2685 }
2686 }
2687 return %TypeAttr;
2688 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002689 else {
2690 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002691 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002692 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002693 else
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002694 { # derived types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002695 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2696 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002697 return ();
2698 }
2699 $TypeAttr{"BaseType"}{"Tid"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002700 if(defined $MissedTypedef{$Version}{$BTid})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002701 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002702 if(my $MissedTDid = $MissedTypedef{$Version}{$BTid}{"TDid"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002703 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002704 if($MissedTDid ne $TypeDeclId) {
2705 $TypeAttr{"BaseType"}{"Tid"} = $MissedTypedef{$Version}{$BTid}{"Tid"};
2706 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002707 }
2708 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002709 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"}{"Tid"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002710 if(not $BTAttr{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002711 { # templates
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002712 return ();
2713 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002714 if($BTAttr{"Type"} eq "Typedef")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002715 { # relinking typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002716 my %BaseBase = get_Type($BTAttr{"BaseType"}{"Tid"}, $Version);
2717 if($BTAttr{"Name"} eq $BaseBase{"Name"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002718 $TypeAttr{"BaseType"}{"Tid"} = $BaseBase{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002719 }
2720 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002721 if($BTSpec)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002722 {
2723 if($TypeAttr{"Type"} eq "Pointer"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002724 and $BTAttr{"Name"}=~/\([\*]+\)/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002725 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002726 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002727 $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g;
2728 }
2729 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002730 $TypeAttr{"Name"} = $BTAttr{"Name"}." ".$BTSpec;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002731 }
2732 }
2733 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002734 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002735 }
2736 if($TypeAttr{"Type"} eq "Typedef")
2737 {
2738 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002739
2740 if(index($TypeAttr{"Name"}, "tmp_add_type")==0) {
2741 return ();
2742 }
2743
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002744 if(isAnon($TypeAttr{"Name"}))
2745 { # anon typedef to anon type: ._N
2746 return ();
2747 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002748 if(my $NS = getNameSpace($TypeDeclId))
2749 {
2750 my $TypeName = $TypeAttr{"Name"};
2751 if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/)
2752 { # "some_type" is the typedef to "struct some_type" in C++
2753 if($3) {
2754 $TypeAttr{"Name"} = $3."::".$TypeName;
2755 }
2756 }
2757 else
2758 {
2759 $TypeAttr{"NameSpace"} = $NS;
2760 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002761
2762 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/
2763 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/)
2764 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002765 if($BTAttr{"NameSpace"}
2766 and $BTAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr{"Name"}=~/</)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002767 { # types like "std::fpos<__mbstate_t>" are
2768 # not covered by typedefs in the TU dump
2769 # so trying to add such typedefs manually
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002770 $StdCxxTypedef{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2771 if(length($TypeAttr{"Name"})<=length($BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002772 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002773 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002774 { # skip "other" in "std" and "type" in "boost"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002775 $Typedef_Eq{$Version}{$BTAttr{"Name"}} = $TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002776 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002777 }
2778 }
2779 }
2780 }
2781 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002782 if($TypeAttr{"Name"} ne $BTAttr{"Name"}
2783 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr{"Name"}!~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002784 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002785 if(not defined $Typedef_BaseName{$Version}{$TypeAttr{"Name"}})
2786 { # typedef int*const TYPEDEF; // first
2787 # int foo(TYPEDEF p); // const is optimized out
2788 $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BTAttr{"Name"};
2789 if($BTAttr{"Name"}=~/</)
2790 {
2791 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) {
2792 $Typedef_Tr{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2793 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002794 }
2795 }
2796 }
2797 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002798
2799 if($LibInfo{$Version}{"info"}{$TypeDeclId}=~/ artificial /i)
2800 { # artificial typedef of "struct X" to "X"
2801 $TypeAttr{"Artificial"} = 1;
2802 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002803 }
2804 if(not $TypeAttr{"Size"})
2805 {
2806 if($TypeAttr{"Type"} eq "Pointer") {
2807 $TypeAttr{"Size"} = $WORD_SIZE{$Version};
2808 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002809 elsif($BTAttr{"Size"}) {
2810 $TypeAttr{"Size"} = $BTAttr{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002811 }
2812 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002813 if(my $Algn = getAlgn($TypeId)) {
2814 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2815 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002816 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002817 if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) {
2818 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002819 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002820 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002821 if($TypeAttr{"Name"} ne $BTAttr{"Name"})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002822 { # typedef to "class Class"
2823 # should not be registered in TName_Tid
2824 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2825 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2826 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002827 }
2828 return %TypeAttr;
2829 }
2830}
2831
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002832sub getTreeVec($)
2833{
2834 my %Vector = ();
2835 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2836 {
2837 while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
2838 { # string length is N-1 because of the null terminator
2839 $Vector{$1} = $2;
2840 }
2841 }
2842 return \%Vector;
2843}
2844
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002845sub get_TemplateParam($$)
2846{
2847 my ($Pos, $Type_Id) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002848 return () if(not $Type_Id);
2849 my $NodeType = $LibInfo{$Version}{"info_type"}{$Type_Id};
2850 return () if(not $NodeType);
2851 if($NodeType eq "integer_cst")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002852 { # int (1), unsigned (2u), char ('c' as 99), ...
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002853 my $CstTid = getTreeAttr_Type($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002854 my %CstType = getTypeAttr($CstTid); # without recursion
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002855 my $Num = getNodeIntCst($Type_Id);
2856 if(my $CstSuffix = $ConstantSuffix{$CstType{"Name"}}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002857 return ($Num.$CstSuffix);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002858 }
2859 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002860 return ("(".$CstType{"Name"}.")".$Num);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002861 }
2862 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002863 elsif($NodeType eq "string_cst") {
2864 return (getNodeStrCst($Type_Id));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002865 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002866 elsif($NodeType eq "tree_vec")
2867 {
2868 my $Vector = getTreeVec($Type_Id);
2869 my @Params = ();
2870 foreach my $P1 (sort {int($a)<=>int($b)} keys(%{$Vector}))
2871 {
2872 foreach my $P2 (get_TemplateParam($Pos, $Vector->{$P1})) {
2873 push(@Params, $P2);
2874 }
2875 }
2876 return @Params;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002877 }
2878 else
2879 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002880 my %ParamAttr = getTypeAttr($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002881 my $PName = $ParamAttr{"Name"};
2882 if(not $PName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002883 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002884 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002885 if($PName=~/\>/)
2886 {
2887 if(my $Cover = cover_stdcxx_typedef($PName)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002888 $PName = $Cover;
2889 }
2890 }
2891 if($Pos>=1 and
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04002892 $PName=~/\A$DEFAULT_STD_PARMS\</)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002893 { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
2894 # template<typename _Key, typename _Compare = std::less<_Key>
2895 # template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
2896 # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> >
2897 # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
2898 # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> >
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002899 return ("\@skip\@");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002900 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002901 return ($PName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002902 }
2903}
2904
2905sub cover_stdcxx_typedef($)
2906{
2907 my $TypeName = $_[0];
2908 if(my @Covers = sort {length($a)<=>length($b)}
2909 sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
2910 { # take the shortest typedef
2911 # FIXME: there may be more than
2912 # one typedefs to the same type
2913 return $Covers[0];
2914 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002915 my $Covered = $TypeName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002916 while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){};
2917 if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
2918 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002919 if(my $Cover = $Covers[0])
2920 {
2921 $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
2922 $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
2923 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002924 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002925 return formatName($Covered, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002926}
2927
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002928sub getNodeIntCst($)
2929{
2930 my $CstId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002931 my $CstTypeId = getTreeAttr_Type($CstId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002932 if($EnumMembName_Id{$Version}{$CstId}) {
2933 return $EnumMembName_Id{$Version}{$CstId};
2934 }
2935 elsif((my $Value = getTreeValue($CstId)) ne "")
2936 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002937 if($Value eq "0")
2938 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002939 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002940 return "false";
2941 }
2942 else {
2943 return "0";
2944 }
2945 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002946 elsif($Value eq "1")
2947 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002948 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002949 return "true";
2950 }
2951 else {
2952 return "1";
2953 }
2954 }
2955 else {
2956 return $Value;
2957 }
2958 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002959 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002960}
2961
2962sub getNodeStrCst($)
2963{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002964 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2965 {
2966 if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002967 {
2968 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "string_cst")
2969 { # string length is N-1 because of the null terminator
2970 return substr($1, 0, $2-1);
2971 }
2972 else
2973 { # identifier_node
2974 return substr($1, 0, $2);
2975 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002976 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002977 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002978 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002979}
2980
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002981sub getMemPtrAttr($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002982{ # function, method and field pointers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002983 my ($PtrId, $TypeId, $Type) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002984 my $MemInfo = $LibInfo{$Version}{"info"}{$PtrId};
2985 if($Type eq "FieldPtr") {
2986 $MemInfo = $LibInfo{$Version}{"info"}{$TypeId};
2987 }
2988 my $MemInfo_Type = $LibInfo{$Version}{"info_type"}{$PtrId};
2989 my $MemPtrName = "";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002990 my %TypeAttr = ("Size"=>$WORD_SIZE{$Version}, "Type"=>$Type, "Tid"=>$TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002991 if($Type eq "MethodPtr")
2992 { # size of "method pointer" may be greater than WORD size
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002993 if(my $Size = getSize($TypeId))
2994 {
2995 $Size/=$BYTE_SIZE;
2996 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002997 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002998 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002999 if(my $Algn = getAlgn($TypeId)) {
3000 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3001 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003002 # Return
3003 if($Type eq "FieldPtr")
3004 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003005 my %ReturnAttr = getTypeAttr($PtrId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003006 if($ReturnAttr{"Name"}) {
3007 $MemPtrName .= $ReturnAttr{"Name"};
3008 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003009 $TypeAttr{"Return"} = $PtrId;
3010 }
3011 else
3012 {
3013 if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /)
3014 {
3015 my $ReturnTypeId = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003016 my %ReturnAttr = getTypeAttr($ReturnTypeId);
3017 if(not $ReturnAttr{"Name"})
3018 { # templates
3019 return ();
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003020 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003021 $MemPtrName .= $ReturnAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003022 $TypeAttr{"Return"} = $ReturnTypeId;
3023 }
3024 }
3025 # Class
3026 if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /)
3027 {
3028 $TypeAttr{"Class"} = $2;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003029 my %Class = getTypeAttr($TypeAttr{"Class"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003030 if($Class{"Name"}) {
3031 $MemPtrName .= " (".$Class{"Name"}."\:\:*)";
3032 }
3033 else {
3034 $MemPtrName .= " (*)";
3035 }
3036 }
3037 else {
3038 $MemPtrName .= " (*)";
3039 }
3040 # Parameters
3041 if($Type eq "FuncPtr"
3042 or $Type eq "MethodPtr")
3043 {
3044 my @ParamTypeName = ();
3045 if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /)
3046 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003047 my $PTypeInfoId = $1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003048 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003049 while($PTypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003050 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003051 my $PTypeInfo = $LibInfo{$Version}{"info"}{$PTypeInfoId};
3052 if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003053 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003054 my $PTypeId = $1;
3055 my %ParamAttr = getTypeAttr($PTypeId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003056 if(not $ParamAttr{"Name"})
3057 { # templates (template_type_parm), etc.
3058 return ();
3059 }
3060 if($ParamAttr{"Name"} eq "void") {
3061 last;
3062 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003063 if($Pos!=0 or $Type ne "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003064 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003065 $TypeAttr{"Param"}{$PPos++}{"type"} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003066 push(@ParamTypeName, $ParamAttr{"Name"});
3067 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003068 if($PTypeInfoId = getNextElem($PTypeInfoId)) {
3069 $Pos+=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003070 }
3071 else {
3072 last;
3073 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003074 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003075 else {
3076 last;
3077 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003078 }
3079 }
3080 $MemPtrName .= " (".join(", ", @ParamTypeName).")";
3081 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003082 $TypeAttr{"Name"} = formatName($MemPtrName, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003083 return %TypeAttr;
3084}
3085
3086sub getTreeTypeName($)
3087{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003088 my $TypeId = $_[0];
3089 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003090 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003091 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "integer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003092 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003093 if(my $Name = getNameByInfo($TypeId))
3094 { # bit_size_type
3095 return $Name;
3096 }
3097 elsif($Info=~/unsigned/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003098 return "unsigned int";
3099 }
3100 else {
3101 return "int";
3102 }
3103 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003104 elsif($Info=~/name[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003105 return getNameByInfo($1);
3106 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003107 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003108 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003109}
3110
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003111sub isFuncPtr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003112{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003113 my $Ptd = pointTo($_[0]);
3114 return 0 if(not $Ptd);
3115 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003116 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003117 if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) {
3118 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003119 }
3120 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003121 if(my $InfoT1 = $LibInfo{$Version}{"info_type"}{$_[0]}
3122 and my $InfoT2 = $LibInfo{$Version}{"info_type"}{$Ptd})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003123 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003124 if($InfoT1 eq "pointer_type"
3125 and $InfoT2 eq "function_type") {
3126 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003127 }
3128 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003129 return 0;
3130}
3131
3132sub isMethodPtr($)
3133{
3134 my $Ptd = pointTo($_[0]);
3135 return 0 if(not $Ptd);
3136 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3137 {
3138 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "record_type"
3139 and $LibInfo{$Version}{"info_type"}{$Ptd} eq "method_type"
3140 and $Info=~/ ptrmem /) {
3141 return 1;
3142 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003143 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003144 return 0;
3145}
3146
3147sub isFieldPtr($)
3148{
3149 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3150 {
3151 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "offset_type"
3152 and $Info=~/ ptrmem /) {
3153 return 1;
3154 }
3155 }
3156 return 0;
3157}
3158
3159sub pointTo($)
3160{
3161 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3162 {
3163 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) {
3164 return $1;
3165 }
3166 }
3167 return "";
3168}
3169
3170sub getTypeTypeByTypeId($)
3171{
3172 my $TypeId = $_[0];
3173 if(my $TType = $LibInfo{$Version}{"info_type"}{$TypeId})
3174 {
3175 my $NType = $NodeType{$TType};
3176 if($NType eq "Intrinsic") {
3177 return $NType;
3178 }
3179 elsif(isFuncPtr($TypeId)) {
3180 return "FuncPtr";
3181 }
3182 elsif(isMethodPtr($TypeId)) {
3183 return "MethodPtr";
3184 }
3185 elsif(isFieldPtr($TypeId)) {
3186 return "FieldPtr";
3187 }
3188 elsif($NType ne "Other") {
3189 return $NType;
3190 }
3191 }
3192 return "Unknown";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003193}
3194
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003195my %UnQual = (
3196 "r"=>"restrict",
3197 "v"=>"volatile",
3198 "c"=>"const",
3199 "cv"=>"const volatile"
3200);
3201
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003202sub getQual($)
3203{
3204 my $TypeId = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003205 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
3206 {
3207 my ($Qual, $To) = ();
3208 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) {
3209 $Qual = $UnQual{$1};
3210 }
3211 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) {
3212 $To = $1;
3213 }
3214 if($Qual and $To) {
3215 return ($Qual, $To);
3216 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003217 }
3218 return ();
3219}
3220
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003221sub getQualType($)
3222{
3223 if($_[0] eq "const volatile") {
3224 return "ConstVolatile";
3225 }
3226 return ucfirst($_[0]);
3227}
3228
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003229sub getTypeType($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003230{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003231 my $TypeId = $_[0];
3232 my $TypeDeclId = getTypeDeclId($TypeId);
3233 if(defined $MissedTypedef{$Version}{$TypeId})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003234 { # support for old GCC versions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003235 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq $TypeDeclId) {
3236 return "Typedef";
3237 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003238 }
3239 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3240 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003241 if(($Qual or $To) and $TypeDeclId
3242 and (getTypeId($TypeDeclId) ne $TypeId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003243 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003244 return getQualType($Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003245 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003246 elsif(not $MissedBase_R{$Version}{$TypeId}
3247 and isTypedef($TypeId)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003248 return "Typedef";
3249 }
3250 elsif($Qual)
3251 { # qualified types
3252 return getQualType($Qual);
3253 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003254
3255 if($Info=~/unql[ ]*:[ ]*\@(\d+)/)
3256 { # typedef struct { ... } name
3257 $TypeTypedef{$Version}{$TypeId} = $1;
3258 }
3259
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003260 my $TypeType = getTypeTypeByTypeId($TypeId);
3261 if($TypeType eq "Struct")
3262 {
3263 if($TypeDeclId
3264 and $LibInfo{$Version}{"info_type"}{$TypeDeclId} eq "template_decl") {
3265 return "Template";
3266 }
3267 }
3268 return $TypeType;
3269}
3270
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003271sub isTypedef($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003272{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003273 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3274 {
3275 my $TDid = getTypeDeclId($_[0]);
3276 if(getNameByInfo($TDid)
3277 and $Info=~/unql[ ]*:[ ]*\@(\d+) /
3278 and getTypeId($TDid) eq $_[0]) {
3279 return $1;
3280 }
3281 }
3282 return 0;
3283}
3284
3285sub selectBaseType($)
3286{
3287 my $TypeId = $_[0];
3288 if(defined $MissedTypedef{$Version}{$TypeId})
3289 { # add missed typedefs
3290 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) {
3291 return ($TypeId, "");
3292 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003293 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003294 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3295 my $InfoType = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003296
3297 my $MB_R = $MissedBase_R{$Version}{$TypeId};
3298 my $MB = $MissedBase{$Version}{$TypeId};
3299
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003300 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003301 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) /
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003302 and (getTypeId($1) ne $TypeId)
3303 and (not $MB_R or getTypeId($1) ne $MB_R))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003304 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003305 return (getTypeId($1), $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003306 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003307 elsif($MB)
3308 { # add base
3309 return ($MB, "");
3310 }
3311 elsif(not $MB_R and my $Bid = isTypedef($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003312 { # typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003313 return ($Bid, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003314 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003315 elsif($Qual or $To)
3316 { # qualified types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003317 return ($To, $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003318 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003319 elsif($InfoType eq "reference_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003320 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003321 if($Info=~/refd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003322 return ($1, "&");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003323 }
3324 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003325 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003326 }
3327 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003328 elsif($InfoType eq "array_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003329 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003330 if($Info=~/elts[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003331 return ($1, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003332 }
3333 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003334 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003335 }
3336 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003337 elsif($InfoType eq "pointer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003338 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003339 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003340 return ($1, "*");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003341 }
3342 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003343 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003344 }
3345 }
3346 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003347 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003348 }
3349}
3350
3351sub getSymbolInfo_All()
3352{
3353 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3354 { # reverse order
3355 if($LibInfo{$Version}{"info_type"}{$_} eq "function_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003356 getSymbolInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003357 }
3358 }
3359}
3360
3361sub getVarInfo_All()
3362{
3363 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3364 { # reverse order
3365 if($LibInfo{$Version}{"info_type"}{$_} eq "var_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003366 getVarInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003367 }
3368 }
3369}
3370
3371sub isBuiltIn($) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003372 return ($_[0] and $_[0]=~/\<built\-in\>|\<internal\>|\A\./);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003373}
3374
3375sub getVarInfo($)
3376{
3377 my $InfoId = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003378 if(my $NSid = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003379 {
3380 my $NSInfoType = $LibInfo{$Version}{"info_type"}{$NSid};
3381 if($NSInfoType and $NSInfoType eq "function_decl") {
3382 return;
3383 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003384 }
3385 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
3386 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
3387 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) {
3388 delete($SymbolInfo{$Version}{$InfoId});
3389 return;
3390 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003391 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId));
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003392 if(not $ShortName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003393 delete($SymbolInfo{$Version}{$InfoId});
3394 return;
3395 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003396 if($ShortName=~/\Atmp_add_class_\d+\Z/) {
3397 delete($SymbolInfo{$Version}{$InfoId});
3398 return;
3399 }
3400 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003401 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
3402 {
3403 if($OSgroup eq "windows")
3404 { # cut the offset
3405 $MnglName=~s/\@\d+\Z//g;
3406 }
3407 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
3408 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003409 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003410 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003411 { # validate mangled name
3412 delete($SymbolInfo{$Version}{$InfoId});
3413 return;
3414 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003415 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003416 and index($ShortName, "_Z")==0)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003417 { # _ZTS, etc.
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003418 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003419 }
3420 if(isPrivateData($SymbolInfo{$Version}{$InfoId}{"MnglName"}))
3421 { # non-public global data
3422 delete($SymbolInfo{$Version}{$InfoId});
3423 return;
3424 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003425 $SymbolInfo{$Version}{$InfoId}{"Data"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003426 if(my $Rid = getTypeId($InfoId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003427 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003428 if(not $TypeInfo{$Version}{$Rid}{"Name"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003429 { # typename_type
3430 delete($SymbolInfo{$Version}{$InfoId});
3431 return;
3432 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003433 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Rid;
3434 my $Val = getDataVal($InfoId, $Rid);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003435 if(defined $Val) {
3436 $SymbolInfo{$Version}{$InfoId}{"Value"} = $Val;
3437 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003438 }
3439 set_Class_And_Namespace($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003440 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3441 {
3442 if(not $TypeInfo{$Version}{$ClassId}{"Name"})
3443 { # templates
3444 delete($SymbolInfo{$Version}{$InfoId});
3445 return;
3446 }
3447 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003448 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
3449 { # extern "C"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003450 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003451 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003452 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003453 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003454 { # --lang=C option
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003455 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003456 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04003457 if(not $CheckHeadersOnly)
3458 {
3459 if(not $SymbolInfo{$Version}{$InfoId}{"Class"})
3460 {
3461 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
3462 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
3463 {
3464 if(link_symbol($ShortName, $Version, "-Deps"))
3465 { # "const" global data is mangled as _ZL... in the TU dump
3466 # but not mangled when compiling a C shared library
3467 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3468 }
3469 }
3470 }
3471 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003472 if($COMMON_LANGUAGE{$Version} eq "C++")
3473 {
3474 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3475 { # for some symbols (_ZTI) the short name is the mangled name
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003476 if(index($ShortName, "_Z")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003477 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3478 }
3479 }
3480 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3481 { # try to mangle symbol (link with libraries)
3482 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = linkSymbol($InfoId);
3483 }
3484 if($OStarget eq "windows")
3485 {
3486 if(my $Mangled = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
3487 { # link MS C++ symbols from library with GCC symbols from headers
3488 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
3489 }
3490 }
3491 }
3492 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) {
3493 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3494 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003495 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3496 {
3497 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
3498 { # non-target symbols
3499 delete($SymbolInfo{$Version}{$InfoId});
3500 return;
3501 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003502 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003503 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
3504 {
3505 if(defined $MissedTypedef{$Version}{$Rid})
3506 {
3507 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
3508 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
3509 }
3510 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003511 }
3512 setFuncAccess($InfoId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003513 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_ZTV")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003514 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
3515 }
3516 if($ShortName=~/\A(_Z|\?)/) {
3517 delete($SymbolInfo{$Version}{$InfoId}{"ShortName"});
3518 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003519
3520 if($ExtraDump) {
3521 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
3522 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003523}
3524
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003525sub isConstType($$)
3526{
3527 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003528 my %Base = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003529 while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003530 %Base = get_OneStep_BaseType($Base{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003531 }
3532 return ($Base{"Type"} eq "Const");
3533}
3534
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003535sub getTrivialName($$)
3536{
3537 my ($TypeInfoId, $TypeId) = @_;
3538 my %TypeAttr = ();
3539 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId);
3540 if(not $TypeAttr{"Name"}) {
3541 $TypeAttr{"Name"} = getTreeTypeName($TypeId);
3542 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003543 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003544 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003545 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003546 if(isAnon($TypeAttr{"Name"}))
3547 {
3548 my $NameSpaceId = $TypeId;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003549 while(my $NSId = getTreeAttr_Scpe(getTypeDeclId($NameSpaceId)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003550 { # searching for a first not anon scope
3551 if($NSId eq $NameSpaceId) {
3552 last;
3553 }
3554 else
3555 {
3556 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId));
3557 if(not $TypeAttr{"NameSpace"}
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003558 or not isAnon($TypeAttr{"NameSpace"})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003559 last;
3560 }
3561 }
3562 $NameSpaceId=$NSId;
3563 }
3564 }
3565 else
3566 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003567 if(my $NameSpaceId = getTreeAttr_Scpe($TypeInfoId))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003568 {
3569 if($NameSpaceId ne $TypeId) {
3570 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId);
3571 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003572 }
3573 }
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003574 if($TypeAttr{"NameSpace"} and not isAnon($TypeAttr{"Name"})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003575 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3576 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003577 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003578 if(isAnon($TypeAttr{"Name"}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003579 { # anon-struct-header.h-line
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003580 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003581 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003582 if($TypeAttr{"NameSpace"}) {
3583 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3584 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003585 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003586 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId}
3587 and getTypeDeclId($TypeId) eq $TypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003588 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003589 my @TParams = getTParams($TypeId, "Type");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003590 if(not @TParams)
3591 { # template declarations with abstract params
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003592 return ("", "");
3593 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003594 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003595 }
3596 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"});
3597}
3598
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003599sub getTrivialTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003600{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003601 my $TypeId = $_[0];
3602 my $TypeInfoId = getTypeDeclId($_[0]);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003603
3604 if($TemplateDecl{$Version}{$TypeId})
3605 { # template_decl
3606 return ();
3607 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003608 if(my $ScopeId = getTreeAttr_Scpe($TypeInfoId))
3609 {
3610 if($TemplateDecl{$Version}{$ScopeId})
3611 { # template_decl
3612 return ();
3613 }
3614 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003615
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003616 my %TypeAttr = ();
3617 if(getTypeTypeByTypeId($TypeId)!~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/) {
3618 return ();
3619 }
3620 setTypeAccess($TypeId, \%TypeAttr);
3621 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
3622 if(isBuiltIn($TypeAttr{"Header"}))
3623 {
3624 delete($TypeAttr{"Header"});
3625 delete($TypeAttr{"Line"});
3626 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003627 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003628 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId);
3629 if(not $TypeAttr{"Name"}) {
3630 return ();
3631 }
3632 if(not $TypeAttr{"NameSpace"}) {
3633 delete($TypeAttr{"NameSpace"});
3634 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003635 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003636 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003637 if(my @TParams = getTParams($TypeId, "Type"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003638 {
3639 foreach my $Pos (0 .. $#TParams) {
3640 $TypeAttr{"TParam"}{$Pos}{"name"}=$TParams[$Pos];
3641 }
3642 }
3643 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003644 if(my $Size = getSize($TypeId))
3645 {
3646 $Size = $Size/$BYTE_SIZE;
3647 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003648 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003649 else
3650 { # declaration only
3651 $TypeAttr{"Forward"} = 1;
3652 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003653
3654 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr);
3655
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003656 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003657 and ($StaticFields or detect_lang($TypeId)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003658 {
3659 $TypeAttr{"Type"} = "Class";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003660 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003661 }
3662 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003663 or $TypeAttr{"Type"} eq "Class")
3664 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003665 my $Skip = setBaseClasses($TypeId, \%TypeAttr);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003666 if($Skip) {
3667 return ();
3668 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003669 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003670 if(my $Algn = getAlgn($TypeId)) {
3671 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3672 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003673 setSpec($TypeId, \%TypeAttr);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003674
3675 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/)
3676 {
3677 if(not $TypedefToAnon{$TypeId}
3678 and not keys(%{$TemplateInstance{$Version}{"Type"}{$TypeId}}))
3679 {
3680 if(not isAnon($TypeAttr{"Name"})) {
3681 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"};
3682 }
3683 }
3684 }
3685
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003686 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003687 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}})
3688 {
3689 my @Entries = split(/\n/, $VTable);
3690 foreach (1 .. $#Entries)
3691 {
3692 my $Entry = $Entries[$_];
3693 if($Entry=~/\A(\d+)\s+(.+)\Z/) {
3694 $TypeAttr{"VTable"}{$1} = $2;
3695 }
3696 }
3697 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04003698
3699 if($TypeAttr{"Type"} eq "Enum")
3700 {
3701 if(not $TypeAttr{"NameSpace"})
3702 {
3703 foreach my $Pos (keys(%{$TypeAttr{"Memb"}}))
3704 {
3705 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"};
3706 $EnumConstants{$Version}{$MName} = {
3707 "Value"=>$TypeAttr{"Memb"}{$Pos}{"value"},
3708 "Header"=>$TypeAttr{"Header"}
3709 };
3710 }
3711 }
3712 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003713 if($ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003714 {
3715 if(defined $TypedefToAnon{$TypeId}) {
3716 $TypeAttr{"AnonTypedef"} = 1;
3717 }
3718 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04003719
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003720 return %TypeAttr;
3721}
3722
3723sub detect_lang($)
3724{
3725 my $TypeId = $_[0];
3726 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003727 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003728 { # GCC 4 fncs-node points to only non-artificial methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003729 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /);
3730 }
3731 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003732 { # GCC 3
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003733 my $Fncs = getTreeAttr_Fncs($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003734 while($Fncs)
3735 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003736 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003737 return 1;
3738 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003739 $Fncs = getTreeAttr_Chan($Fncs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003740 }
3741 }
3742 return 0;
3743}
3744
3745sub setSpec($$)
3746{
3747 my ($TypeId, $TypeAttr) = @_;
3748 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3749 if($Info=~/\s+spec\s+/) {
3750 $TypeAttr->{"Spec"} = 1;
3751 }
3752}
3753
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003754sub setBaseClasses($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003755{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003756 my ($TypeId, $TypeAttr) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003757 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3758 if($Info=~/binf[ ]*:[ ]*@(\d+) /)
3759 {
3760 $Info = $LibInfo{$Version}{"info"}{$1};
3761 my $Pos = 0;
3762 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //)
3763 {
3764 my ($Access, $BInfoId) = ($1, $2);
3765 my $ClassId = getBinfClassId($BInfoId);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003766 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId};
3767 if(not $CType or $CType eq "template_type_parm"
3768 or $CType eq "typename_type")
3769 { # skip
3770 return 1;
3771 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003772 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId};
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003773 if($Access=~/prot/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003774 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected";
3775 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003776 elsif($Access=~/priv/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003777 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private";
3778 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003779 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003780 if($BaseInfo=~/virt/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003781 { # virtual base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003782 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1;
3783 }
3784 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003785 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003786 }
3787 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003788 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003789}
3790
3791sub getBinfClassId($)
3792{
3793 my $Info = $LibInfo{$Version}{"info"}{$_[0]};
3794 $Info=~/type[ ]*:[ ]*@(\d+) /;
3795 return $1;
3796}
3797
3798sub unmangledFormat($$)
3799{
3800 my ($Name, $LibVersion) = @_;
3801 $Name = uncover_typedefs($Name, $LibVersion);
3802 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){};
3803 $Name=~s/\(\w+\)(\d)/$1/;
3804 return $Name;
3805}
3806
3807sub modelUnmangled($$)
3808{
3809 my ($InfoId, $Compiler) = @_;
3810 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) {
3811 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId};
3812 }
3813 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
3814 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
3815 $PureSignature = "~".$PureSignature;
3816 }
3817 if(not $SymbolInfo{$Version}{$InfoId}{"Data"})
3818 {
3819 my (@Params, @ParamTypes) = ();
3820 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"}
3821 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
3822 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}});
3823 }
3824 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
3825 { # checking parameters
3826 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003827 my %PType = get_PureType($PId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003828 my $PTName = unmangledFormat($PType{"Name"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003829 $PTName=~s/\b(restrict|register)\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003830 if($Compiler eq "MSVC") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003831 $PTName=~s/\blong long\b/__int64/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003832 }
3833 @ParamTypes = (@ParamTypes, $PTName);
3834 }
3835 if(@ParamTypes) {
3836 $PureSignature .= "(".join(", ", @ParamTypes).")";
3837 }
3838 else
3839 {
3840 if($Compiler eq "MSVC")
3841 {
3842 $PureSignature .= "(void)";
3843 }
3844 else
3845 { # GCC
3846 $PureSignature .= "()";
3847 }
3848 }
3849 $PureSignature = delete_keywords($PureSignature);
3850 }
3851 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3852 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003853 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003854 $PureSignature = $ClassName."::".$PureSignature;
3855 }
3856 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) {
3857 $PureSignature = $NS."::".$PureSignature;
3858 }
3859 if($SymbolInfo{$Version}{$InfoId}{"Const"}) {
3860 $PureSignature .= " const";
3861 }
3862 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) {
3863 $PureSignature .= " volatile";
3864 }
3865 my $ShowReturn = 0;
3866 if($Compiler eq "MSVC"
3867 and $SymbolInfo{$Version}{$InfoId}{"Data"})
3868 {
3869 $ShowReturn=1;
3870 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003871 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId}
3872 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003873 {
3874 $ShowReturn=1;
3875 }
3876 if($ShowReturn)
3877 { # mangled names for template function specializations include return value
3878 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
3879 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003880 my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003881 my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
3882 $PureSignature = $ReturnName." ".$PureSignature;
3883 }
3884 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003885 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature, "S"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003886}
3887
3888sub mangle_symbol($$$)
3889{ # mangling for simple methods
3890 # see gcc-4.6.0/gcc/cp/mangle.c
3891 my ($InfoId, $LibVersion, $Compiler) = @_;
3892 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) {
3893 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler};
3894 }
3895 my $Mangled = "";
3896 if($Compiler eq "GCC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003897 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003898 }
3899 elsif($Compiler eq "MSVC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003900 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003901 }
3902 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled);
3903}
3904
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003905sub mangle_symbol_MSVC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003906{
3907 my ($InfoId, $LibVersion) = @_;
3908 return "";
3909}
3910
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003911sub mangle_symbol_GCC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003912{ # see gcc-4.6.0/gcc/cp/mangle.c
3913 my ($InfoId, $LibVersion) = @_;
3914 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003915 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003916 my %Repl = ();# SN_ replacements
3917 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
3918 {
3919 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl);
3920 if($MangledClass!~/\AN/) {
3921 $MangledClass = "N".$MangledClass;
3922 }
3923 else {
3924 $MangledClass=~s/E\Z//;
3925 }
3926 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) {
3927 $MangledClass=~s/\AN/NV/;
3928 }
3929 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) {
3930 $MangledClass=~s/\AN/NK/;
3931 }
3932 $Mangled .= $MangledClass;
3933 }
3934 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"})
3935 { # mangled by name due to the absence of structured info
3936 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl);
3937 if($MangledNS!~/\AN/) {
3938 $MangledNS = "N".$MangledNS;
3939 }
3940 else {
3941 $MangledNS=~s/E\Z//;
3942 }
3943 $Mangled .= $MangledNS;
3944 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04003945 my ($ShortName, $TmplParams) = template_Base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003946 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003947 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003948 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003949 foreach (@TPos) {
3950 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"});
3951 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003952 }
3953 elsif($TmplParams)
3954 { # remangling mode
3955 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04003956 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003957 }
3958 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) {
3959 $Mangled .= "C1";
3960 }
3961 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
3962 $Mangled .= "D0";
3963 }
3964 elsif($ShortName)
3965 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003966 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
3967 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003968 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003969 and isConstType($Return, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003970 { # "const" global data is mangled as _ZL...
3971 $Mangled .= "L";
3972 }
3973 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003974 if($ShortName=~/\Aoperator(\W.*)\Z/)
3975 {
3976 my $Op = $1;
3977 $Op=~s/\A[ ]+//g;
3978 if(my $OpMngl = $OperatorMangling{$Op}) {
3979 $Mangled .= $OpMngl;
3980 }
3981 else { # conversion operator
3982 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl);
3983 }
3984 }
3985 else {
3986 $Mangled .= length($ShortName).$ShortName;
3987 }
3988 if(@TParams)
3989 { # templates
3990 $Mangled .= "I";
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04003991 foreach my $TParam (@TParams) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003992 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl);
3993 }
3994 $Mangled .= "E";
3995 }
3996 if(not $ClassId and @TParams) {
3997 add_substitution($ShortName, \%Repl, 0);
3998 }
3999 }
4000 if($ClassId or $NameSpace) {
4001 $Mangled .= "E";
4002 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004003 if(@TParams)
4004 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004005 if($Return) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004006 $Mangled .= mangle_param($Return, $LibVersion, \%Repl);
4007 }
4008 }
4009 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4010 {
4011 my @Params = ();
4012 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
4013 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4014 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
4015 }
4016 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4017 { # checking parameters
4018 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"};
4019 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl);
4020 }
4021 if(not @Params) {
4022 $Mangled .= "v";
4023 }
4024 }
4025 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled);
4026 $Mangled = write_stdcxx_substitution($Mangled);
4027 if($Mangled eq "_Z") {
4028 return "";
4029 }
4030 return $Mangled;
4031}
4032
4033sub correct_incharge($$$)
4034{
4035 my ($InfoId, $LibVersion, $Mangled) = @_;
4036 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"})
4037 {
4038 if($MangledNames{$LibVersion}{$Mangled}) {
4039 $Mangled=~s/C1E/C2E/;
4040 }
4041 }
4042 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
4043 {
4044 if($MangledNames{$LibVersion}{$Mangled}) {
4045 $Mangled=~s/D0E/D1E/;
4046 }
4047 if($MangledNames{$LibVersion}{$Mangled}) {
4048 $Mangled=~s/D1E/D2E/;
4049 }
4050 }
4051 return $Mangled;
4052}
4053
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004054sub template_Base($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004055{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004056 # NOTE: operators: >>, <<
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004057 my $Name = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004058 if($Name!~/>\Z/ or $Name!~/</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004059 return $Name;
4060 }
4061 my $TParams = $Name;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004062 while(my $CPos = find_center($TParams, "<"))
4063 { # search for the last <T>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004064 $TParams = substr($TParams, $CPos);
4065 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004066 if($TParams=~s/\A<(.+)>\Z/$1/) {
4067 $Name=~s/<\Q$TParams\E>\Z//;
4068 }
4069 else
4070 { # error
4071 $TParams = "";
4072 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004073 return ($Name, $TParams);
4074}
4075
4076sub get_sub_ns($)
4077{
4078 my $Name = $_[0];
4079 my @NS = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004080 while(my $CPos = find_center($Name, ":"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004081 {
4082 push(@NS, substr($Name, 0, $CPos));
4083 $Name = substr($Name, $CPos);
4084 $Name=~s/\A:://;
4085 }
4086 return (join("::", @NS), $Name);
4087}
4088
4089sub mangle_ns($$$)
4090{
4091 my ($Name, $LibVersion, $Repl) = @_;
4092 if(my $Tid = $TName_Tid{$LibVersion}{$Name})
4093 {
4094 my $Mangled = mangle_param($Tid, $LibVersion, $Repl);
4095 $Mangled=~s/\AN(.+)E\Z/$1/;
4096 return $Mangled;
4097
4098 }
4099 else
4100 {
4101 my ($MangledNS, $SubNS) = ("", "");
4102 ($SubNS, $Name) = get_sub_ns($Name);
4103 if($SubNS) {
4104 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4105 }
4106 $MangledNS .= length($Name).$Name;
4107 add_substitution($MangledNS, $Repl, 0);
4108 return $MangledNS;
4109 }
4110}
4111
4112sub mangle_param($$$)
4113{
4114 my ($PTid, $LibVersion, $Repl) = @_;
4115 my ($MPrefix, $Mangled) = ("", "");
4116 my %ReplCopy = %{$Repl};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004117 my %BaseType = get_BaseType($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004118 my $BaseType_Name = $BaseType{"Name"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004119 $BaseType_Name=~s/\A(struct|union|enum) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004120 if(not $BaseType_Name) {
4121 return "";
4122 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004123 my ($ShortName, $TmplParams) = template_Base($BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004124 my $Suffix = get_BaseTypeQual($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004125 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){};
4126 while($Suffix=~/(&|\*|const)\Z/)
4127 {
4128 if($Suffix=~s/[ ]*&\Z//) {
4129 $MPrefix .= "R";
4130 }
4131 if($Suffix=~s/[ ]*\*\Z//) {
4132 $MPrefix .= "P";
4133 }
4134 if($Suffix=~s/[ ]*const\Z//)
4135 {
4136 if($MPrefix=~/R|P/
4137 or $Suffix=~/&|\*/) {
4138 $MPrefix .= "K";
4139 }
4140 }
4141 if($Suffix=~s/[ ]*volatile\Z//) {
4142 $MPrefix .= "V";
4143 }
4144 #if($Suffix=~s/[ ]*restrict\Z//) {
4145 #$MPrefix .= "r";
4146 #}
4147 }
4148 if(my $Token = $IntrinsicMangling{$BaseType_Name}) {
4149 $Mangled .= $Token;
4150 }
4151 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/)
4152 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004153 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004154 if(my @TPos = keys(%{$BaseType{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004155 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004156 foreach (@TPos) {
4157 push(@TParams, $BaseType{"TParam"}{$_}{"name"});
4158 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004159 }
4160 elsif($TmplParams)
4161 { # remangling mode
4162 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004163 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004164 }
4165 my $MangledNS = "";
4166 my ($SubNS, $SName) = get_sub_ns($ShortName);
4167 if($SubNS) {
4168 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4169 }
4170 $MangledNS .= length($SName).$SName;
4171 if(@TParams) {
4172 add_substitution($MangledNS, $Repl, 0);
4173 }
4174 $Mangled .= "N".$MangledNS;
4175 if(@TParams)
4176 { # templates
4177 $Mangled .= "I";
4178 foreach my $TParam (@TParams) {
4179 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl);
4180 }
4181 $Mangled .= "E";
4182 }
4183 $Mangled .= "E";
4184 }
4185 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/)
4186 {
4187 if($BaseType{"Type"} eq "MethodPtr") {
4188 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F";
4189 }
4190 else {
4191 $Mangled .= "PF";
4192 }
4193 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4194 my @Params = keys(%{$BaseType{"Param"}});
4195 foreach my $Num (sort {int($a)<=>int($b)} @Params) {
4196 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl);
4197 }
4198 if(not @Params) {
4199 $Mangled .= "v";
4200 }
4201 $Mangled .= "E";
4202 }
4203 elsif($BaseType{"Type"} eq "FieldPtr")
4204 {
4205 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl);
4206 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4207 }
4208 $Mangled = $MPrefix.$Mangled;# add prefix (RPK)
4209 if(my $Optimized = write_substitution($Mangled, \%ReplCopy))
4210 {
4211 if($Mangled eq $Optimized)
4212 {
4213 if($ShortName!~/::/)
4214 { # remove "N ... E"
4215 if($MPrefix) {
4216 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g;
4217 }
4218 else {
4219 $Mangled=~s/\AN(.+)E\Z/$1/g;
4220 }
4221 }
4222 }
4223 else {
4224 $Mangled = $Optimized;
4225 }
4226 }
4227 add_substitution($Mangled, $Repl, 1);
4228 return $Mangled;
4229}
4230
4231sub mangle_template_param($$$)
4232{ # types + literals
4233 my ($TParam, $LibVersion, $Repl) = @_;
4234 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) {
4235 return mangle_param($TPTid, $LibVersion, $Repl);
4236 }
4237 elsif($TParam=~/\A(\d+)(\w+)\Z/)
4238 { # class_name<1u>::method(...)
4239 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E";
4240 }
4241 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/)
4242 { # class_name<(signed char)1>::method(...)
4243 return "L".$IntrinsicMangling{$1}.$2."E";
4244 }
4245 elsif($TParam eq "true")
4246 { # class_name<true>::method(...)
4247 return "Lb1E";
4248 }
4249 elsif($TParam eq "false")
4250 { # class_name<true>::method(...)
4251 return "Lb0E";
4252 }
4253 else { # internal error
4254 return length($TParam).$TParam;
4255 }
4256}
4257
4258sub add_substitution($$$)
4259{
4260 my ($Value, $Repl, $Rec) = @_;
4261 if($Rec)
4262 { # subtypes
4263 my @Subs = ($Value);
4264 while($Value=~s/\A(R|P|K)//) {
4265 push(@Subs, $Value);
4266 }
4267 foreach (reverse(@Subs)) {
4268 add_substitution($_, $Repl, 0);
4269 }
4270 return;
4271 }
4272 return if($Value=~/\AS(\d*)_\Z/);
4273 $Value=~s/\AN(.+)E\Z/$1/g;
4274 return if(defined $Repl->{$Value});
4275 return if(length($Value)<=1);
4276 return if($StdcxxMangling{$Value});
4277 # check for duplicates
4278 my $Base = $Value;
4279 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4280 {
4281 my $Num = $Repl->{$Type};
4282 my $Replace = macro_mangle($Num);
4283 $Base=~s/\Q$Replace\E/$Type/;
4284 }
4285 if(my $OldNum = $Repl->{$Base})
4286 {
4287 $Repl->{$Value} = $OldNum;
4288 return;
4289 }
4290 my @Repls = sort {$b<=>$a} values(%{$Repl});
4291 if(@Repls) {
4292 $Repl->{$Value} = $Repls[0]+1;
4293 }
4294 else {
4295 $Repl->{$Value} = -1;
4296 }
4297 # register duplicates
4298 # upward
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004299 $Base = $Value;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004300 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4301 {
4302 next if($Base eq $Type);
4303 my $Num = $Repl->{$Type};
4304 my $Replace = macro_mangle($Num);
4305 $Base=~s/\Q$Type\E/$Replace/;
4306 $Repl->{$Base} = $Repl->{$Value};
4307 }
4308}
4309
4310sub macro_mangle($)
4311{
4312 my $Num = $_[0];
4313 if($Num==-1) {
4314 return "S_";
4315 }
4316 else
4317 {
4318 my $Code = "";
4319 if($Num<10)
4320 { # S0_, S1_, S2_, ...
4321 $Code = $Num;
4322 }
4323 elsif($Num>=10 and $Num<=35)
4324 { # SA_, SB_, SC_, ...
4325 $Code = chr(55+$Num);
4326 }
4327 else
4328 { # S10_, S11_, S12_
4329 $Code = $Num-26; # 26 is length of english alphabet
4330 }
4331 return "S".$Code."_";
4332 }
4333}
4334
4335sub write_stdcxx_substitution($)
4336{
4337 my $Mangled = $_[0];
4338 if($StdcxxMangling{$Mangled}) {
4339 return $StdcxxMangling{$Mangled};
4340 }
4341 else
4342 {
4343 my @Repls = keys(%StdcxxMangling);
4344 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4345 foreach my $MangledType (@Repls)
4346 {
4347 my $Replace = $StdcxxMangling{$MangledType};
4348 #if($Mangled!~/$Replace/) {
4349 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4350 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4351 #}
4352 }
4353 }
4354 return $Mangled;
4355}
4356
4357sub write_substitution($$)
4358{
4359 my ($Mangled, $Repl) = @_;
4360 if(defined $Repl->{$Mangled}
4361 and my $MnglNum = $Repl->{$Mangled}) {
4362 $Mangled = macro_mangle($MnglNum);
4363 }
4364 else
4365 {
4366 my @Repls = keys(%{$Repl});
4367 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls;
4368 # FIXME: how to apply replacements? by num or by pos
4369 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4370 foreach my $MangledType (@Repls)
4371 {
4372 my $Replace = macro_mangle($Repl->{$MangledType});
4373 if($Mangled!~/$Replace/) {
4374 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4375 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4376 }
4377 }
4378 }
4379 return $Mangled;
4380}
4381
4382sub delete_keywords($)
4383{
4384 my $TypeName = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004385 $TypeName=~s/\b(enum|struct|union|class) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004386 return $TypeName;
4387}
4388
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004389sub uncover_typedefs($$)
4390{
4391 my ($TypeName, $LibVersion) = @_;
4392 return "" if(not $TypeName);
4393 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) {
4394 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName};
4395 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004396 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName, "T"), "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004397 while($TypeName_New ne $TypeName_Pre)
4398 {
4399 $TypeName_Pre = $TypeName_New;
4400 my $TypeName_Copy = $TypeName_New;
4401 my %Words = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004402 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004403 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004404 if(not $Intrinsic_Keywords{$1}) {
4405 $Words{$1} = 1;
4406 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004407 }
4408 foreach my $Word (keys(%Words))
4409 {
4410 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word};
4411 next if(not $BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004412 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004413 if($BaseType_Name=~/\([\*]+\)/)
4414 { # FuncPtr
4415 if($TypeName_New=~/\Q$Word\E(.*)\Z/)
4416 {
4417 my $Type_Suffix = $1;
4418 $TypeName_New = $BaseType_Name;
4419 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004420 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004421 }
4422 }
4423 }
4424 else
4425 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004426 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004427 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004428 }
4429 }
4430 }
4431 }
4432 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New);
4433}
4434
4435sub isInternal($)
4436{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004437 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4438 {
4439 if($Info=~/mngl[ ]*:[ ]*@(\d+) /)
4440 {
4441 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/)
4442 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL*
4443 return 1;
4444 }
4445 }
4446 }
4447 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004448}
4449
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004450sub getDataVal($$)
4451{
4452 my ($InfoId, $TypeId) = @_;
4453 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4454 {
4455 if($Info=~/init[ ]*:[ ]*@(\d+) /)
4456 {
4457 if(defined $LibInfo{$Version}{"info_type"}{$1}
4458 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr")
4459 { # char const* data = "str"
4460 # NOTE: disabled
4461 if(my $NopExpr = $LibInfo{$Version}{"info"}{$1})
4462 {
4463 if($NopExpr=~/op 0[ ]*:[ ]*@(\d+) /)
4464 {
4465 if(defined $LibInfo{$Version}{"info_type"}{$1}
4466 and $LibInfo{$Version}{"info_type"}{$1} eq "addr_expr")
4467 {
4468 if(my $AddrExpr = $LibInfo{$Version}{"info"}{$1})
4469 {
4470 if($AddrExpr=~/op 0[ ]*:[ ]*@(\d+) /)
4471 {
4472 return getInitVal($1, $TypeId);
4473 }
4474 }
4475 }
4476 }
4477 }
4478 }
4479 else {
4480 return getInitVal($1, $TypeId);
4481 }
4482 }
4483 }
4484 return undef;
4485}
4486
4487sub getInitVal($$)
4488{
4489 my ($InfoId, $TypeId) = @_;
4490 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4491 {
4492 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId})
4493 {
4494 if($InfoType eq "integer_cst")
4495 {
4496 my $Val = getNodeIntCst($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004497 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004498 { # characters
4499 $Val = chr($Val);
4500 }
4501 return $Val;
4502 }
4503 elsif($InfoType eq "string_cst") {
4504 return getNodeStrCst($InfoId);
4505 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004506 elsif($InfoType eq "var_decl")
4507 {
4508 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) {
4509 return $Name;
4510 }
4511 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004512 }
4513 }
4514 return undef;
4515}
4516
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004517sub set_Class_And_Namespace($)
4518{
4519 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004520 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004521 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004522 if($Info=~/scpe[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004523 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004524 my $NSInfoId = $1;
4525 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
4526 {
4527 if($InfoType eq "namespace_decl") {
4528 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId);
4529 }
4530 elsif($InfoType eq "record_type") {
4531 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId;
4532 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004533 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004534 }
4535 }
4536 if($SymbolInfo{$Version}{$InfoId}{"Class"}
4537 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"})
4538 { # identify language
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004539 if($COMMON_LANGUAGE{$Version} ne "C++")
4540 {
4541 if(my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"})
4542 {
4543 if(index($ShortName, "__")!=0)
4544 { # skip C++ symbols from pthread.h:
4545 # __pthread_cleanup_class, __restore, __defer, __setdoit, etc.
4546 setLanguage($Version, "C++");
4547 }
4548 }
4549 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004550 }
4551}
4552
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004553sub debugMangling($)
4554{
4555 my $LibVersion = $_[0];
4556 my %Mangled = ();
4557 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
4558 {
4559 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
4560 {
4561 if($Mngl=~/\A(_Z|\?)/) {
4562 $Mangled{$Mngl}=$InfoId;
4563 }
4564 }
4565 }
4566 translateSymbols(keys(%Mangled), $LibVersion);
4567 foreach my $Mngl (keys(%Mangled))
4568 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004569 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC");
4570 my $U2 = $tr_name{$Mngl};
4571 if($U1 ne $U2) {
4572 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004573 }
4574 }
4575}
4576
4577sub linkSymbol($)
4578{ # link symbols from shared libraries
4579 # with the symbols from header files
4580 my $InfoId = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004581 # try to mangle symbol
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004582 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"})
4583 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004584 { # 1. GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
4585 # 2. GCC 4.x doesn't mangle C++ functions in the TU dump (only class methods) except extern "C" functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004586 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004587 {
4588 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
4589 return correct_incharge($InfoId, $Version, $Mangled);
4590 }
4591 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004592 if($CheckHeadersOnly
4593 or not $BinaryOnly)
4594 { # 1. --headers-only mode
4595 # 2. not mangled src-only symbols
4596 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) {
4597 return $Mangled;
4598 }
4599 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004600 }
4601 return "";
4602}
4603
4604sub setLanguage($$)
4605{
4606 my ($LibVersion, $Lang) = @_;
4607 if(not $UserLang) {
4608 $COMMON_LANGUAGE{$LibVersion} = $Lang;
4609 }
4610}
4611
4612sub getSymbolInfo($)
4613{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004614 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004615 if(isInternal($InfoId)) {
4616 return;
4617 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004618 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
4619 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004620 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"}))
4621 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004622 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004623 return;
4624 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004625 setFuncAccess($InfoId);
4626 setFuncKind($InfoId);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004627 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"})
4628 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004629 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004630 return;
4631 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004632
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004633 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004634 if($SymbolInfo{$Version}{$InfoId}{"Return"} = getFuncReturn($InfoId))
4635 {
4636 if(not $TypeInfo{$Version}{$SymbolInfo{$Version}{$InfoId}{"Return"}}{"Name"})
4637 { # templates
4638 delete($SymbolInfo{$Version}{$InfoId});
4639 return;
4640 }
4641 }
4642 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
4643 {
4644 if(defined $MissedTypedef{$Version}{$Rid})
4645 {
4646 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
4647 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
4648 }
4649 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004650 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004651 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) {
4652 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004653 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004654 my $Orig = getFuncOrig($InfoId);
4655 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004656 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "\._")!=-1)
4657 {
4658 delete($SymbolInfo{$Version}{$InfoId});
4659 return;
4660 }
4661
4662 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "tmp_add_func")==0)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004663 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004664 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004665 return;
4666 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004667
4668 if(defined $TemplateInstance{$Version}{"Func"}{$Orig})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004669 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004670 my @TParams = getTParams($Orig, "Func");
4671 if(not @TParams)
4672 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004673 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004674 return;
4675 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004676 foreach my $Pos (0 .. $#TParams) {
4677 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"}=$TParams[$Pos];
4678 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004679 my $PrmsInLine = join(", ", @TParams);
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004680 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/)
4681 { # operator<< <T>, operator>> <T>
4682 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " ";
4683 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004684 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".$PrmsInLine.">";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004685 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "S");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004686 }
4687 else
4688 { # support for GCC 3.4
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004689 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004690 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004691 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
4692 {
4693 if($OSgroup eq "windows")
4694 { # cut the offset
4695 $MnglName=~s/\@\d+\Z//g;
4696 }
4697 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
4698
4699 # NOTE: mangling of some symbols may change depending on GCC version
4700 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
4701 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
4702 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004703
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004704 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004705 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004706 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004707 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004708 return;
4709 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004710 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004711 { # destructors have an empty parameter list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004712 my $Skip = setFuncParams($InfoId);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004713 if($Skip)
4714 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004715 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004716 return;
4717 }
4718 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004719 set_Class_And_Namespace($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004720 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
4721 {
4722 if(not $TypeInfo{$Version}{$ClassId}{"Name"})
4723 { # templates
4724 delete($SymbolInfo{$Version}{$InfoId});
4725 return;
4726 }
4727 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004728 if(not $CheckHeadersOnly)
4729 {
4730 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function"
4731 and not $SymbolInfo{$Version}{$InfoId}{"Class"}
4732 and link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps"))
4733 { # functions (C++): not mangled in library, but are mangled in TU dump
4734 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
4735 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps")) {
4736 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4737 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004738 }
4739 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004740 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
4741 { # extern "C"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004742 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004743 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004744 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004745 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004746 { # --lang=C option
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004747 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004748 }
4749 if($COMMON_LANGUAGE{$Version} eq "C++")
4750 { # correct mangled & short names
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004751 # C++ or --headers-only mode
4752 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004753 { # support for old GCC versions: reconstruct real names for constructors and destructors
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004754 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"}));
4755 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004756 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004757 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004758 { # try to mangle symbol (link with libraries)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004759 if(my $Mangled = linkSymbol($InfoId)) {
4760 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004761 }
4762 }
4763 if($OStarget eq "windows")
4764 { # link MS C++ symbols from library with GCC symbols from headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004765 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004766 { # exported symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004767 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004768 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004769 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004770 { # pure virtual symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004771 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004772 }
4773 }
4774 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004775 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004776 { # can't detect symbol name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004777 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004778 return;
4779 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004780 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004781 and my $Spec = getVirtSpec($Orig))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004782 { # identify virtual and pure virtual functions
4783 # NOTE: constructors cannot be virtual
4784 # NOTE: in GCC 4.7 D1 destructors have no virtual spec
4785 # in the TU dump, so taking it from the original symbol
4786 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"}
4787 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/))
4788 { # NOTE: D2 destructors are not present in a v-table
4789 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1;
4790 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004791 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004792 if(isInline($InfoId)) {
4793 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004794 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004795 if(hasThrow($InfoId)) {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04004796 $SymbolInfo{$Version}{$InfoId}{"Throw"} = 1;
4797 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04004798 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) {
4799 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1;
4800 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004801 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
4802 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004803 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004804 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"}
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04004805 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004806 { # inline or auto-generated constructor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004807 delete($TypeInfo{$Version}{$ClassId}{"Copied"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004808 }
4809 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004810 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
4811 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004812 if(not $ExtraDump)
4813 {
4814 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
4815 { # non-target symbols
4816 delete($SymbolInfo{$Version}{$InfoId});
4817 return;
4818 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004819 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004820 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004821 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method"
4822 or $SymbolInfo{$Version}{$InfoId}{"Constructor"}
4823 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}
4824 or $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004825 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004826 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/)
4827 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004828 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004829 return;
4830 }
4831 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004832 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004833 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004834 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004835 { # one instance for one mangled name only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004836 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004837 return;
4838 }
4839 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004840 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004841 }
4842 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004843 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
4844 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4845 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004846 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004847 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/
4848 and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004849 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004850 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004851 { # static methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004852 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004853 }
4854 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004855 if(getFuncLink($InfoId) eq "Static") {
4856 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004857 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004858 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/)
4859 {
4860 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
4861 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004862 if($Unmangled=~/\.\_\d/)
4863 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004864 delete($SymbolInfo{$Version}{$InfoId});
4865 return;
4866 }
4867 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004868 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004869 delete($SymbolInfo{$Version}{$InfoId}{"Type"});
4870 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) {
4871 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004872 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004873 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) {
4874 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004875 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004876
4877 if($WeakSymbols{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) {
4878 $SymbolInfo{$Version}{$InfoId}{"Weak"} = 1;
4879 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004880
4881 if($ExtraDump) {
4882 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
4883 }
4884}
4885
4886sub guessHeader($)
4887{
4888 my $InfoId = $_[0];
4889 my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4890 my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"};
4891 my $ClassName = $ClassId?get_ShortClass($ClassId, $Version):"";
4892 my $Header = $SymbolInfo{$Version}{$InfoId}{"Header"};
4893 if(my $HPath = $SymbolHeader{$Version}{$ClassName}{$ShortName})
4894 {
4895 if(get_filename($HPath) eq $Header)
4896 {
4897 my $HDir = get_filename(get_dirname($HPath));
4898 if($HDir ne "include"
4899 and $HDir=~/\A[a-z]+\Z/i) {
4900 return join_P($HDir, $Header);
4901 }
4902 }
4903 }
4904 return $Header;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004905}
4906
4907sub isInline($)
4908{ # "body: undefined" in the tree
4909 # -fkeep-inline-functions GCC option should be specified
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004910 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4911 {
4912 if($Info=~/ undefined /i) {
4913 return 0;
4914 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004915 }
4916 return 1;
4917}
4918
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04004919sub hasThrow($)
4920{
4921 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4922 {
4923 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
4924 return getTreeAttr_Unql($1, "unql");
4925 }
4926 }
4927 return 1;
4928}
4929
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004930sub getTypeId($)
4931{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004932 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4933 {
4934 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
4935 return $1;
4936 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004937 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004938 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004939}
4940
4941sub setTypeMemb($$)
4942{
4943 my ($TypeId, $TypeAttr) = @_;
4944 my $TypeType = $TypeAttr->{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004945 my ($Pos, $UnnamedPos) = (0, 0);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004946 my $StaticFields = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004947 if($TypeType eq "Enum")
4948 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004949 my $MInfoId = getTreeAttr_Csts($TypeId);
4950 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004951 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004952 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId);
4953 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004954 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004955 $EnumMembName_Id{$Version}{getTreeAttr_Valu($MInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
4956 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004957 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004958 }
4959 }
4960 elsif($TypeType=~/\A(Struct|Class|Union)\Z/)
4961 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004962 my $MInfoId = getTreeAttr_Flds($TypeId);
4963 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004964 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004965 my $IType = $LibInfo{$Version}{"info_type"}{$MInfoId};
4966 my $MInfo = $LibInfo{$Version}{"info"}{$MInfoId};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004967 if(not $IType or $IType ne "field_decl")
4968 { # search for fields, skip other stuff in the declaration
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004969
4970 if($IType eq "var_decl")
4971 { # static field
4972 $StaticFields = 1;
4973 }
4974
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004975 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004976 next;
4977 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004978 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId));
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004979 if(index($StructMembName, "_vptr.")!=-1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004980 { # virtual tables
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004981 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004982 next;
4983 }
4984 if(not $StructMembName)
4985 { # unnamed fields
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004986 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004987 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004988 my $UnnamedTid = getTreeAttr_Type($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004989 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid));
4990 if(isAnon($UnnamedTName))
4991 { # rename unnamed fields to unnamed0, unnamed1, ...
4992 $StructMembName = "unnamed".($UnnamedPos++);
4993 }
4994 }
4995 }
4996 if(not $StructMembName)
4997 { # unnamed fields and base classes
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004998 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004999 next;
5000 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005001 my $MembTypeId = getTreeAttr_Type($MInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005002 if(defined $MissedTypedef{$Version}{$MembTypeId})
5003 {
5004 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) {
5005 $MembTypeId = $AddedTid;
5006 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005007 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005008 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId;
5009 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005010 if((my $Access = getTreeAccess($MInfoId)) ne "public")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005011 { # marked only protected and private, public by default
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005012 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access;
5013 }
5014 if($MInfo=~/spec:\s*mutable /)
5015 { # mutable fields
5016 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005017 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005018 if(my $Algn = getAlgn($MInfoId)) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005019 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
5020 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005021 if(my $BFSize = getBitField($MInfoId))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005022 { # in bits
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005023 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005024 }
5025 else
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005026 { # in bytes
5027 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005028 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005029
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005030 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005031 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005032 }
5033 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005034
5035 return $StaticFields;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005036}
5037
5038sub setFuncParams($)
5039{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005040 my $InfoId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005041 my $ParamInfoId = getTreeAttr_Args($InfoId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005042 if(getFuncType($InfoId) eq "Method")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005043 { # check type of "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005044 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId);
5045 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005046 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005047 if($ObjectName=~/\bconst(| volatile)\*const\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005048 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
5049 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005050 if($ObjectName=~/\bvolatile\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005051 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
5052 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005053 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005054 else
5055 { # skip
5056 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005057 }
5058 $ParamInfoId = getNextElem($ParamInfoId);
5059 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005060 my ($Pos, $Vtt_Pos) = (0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005061 while($ParamInfoId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005062 { # formal args
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005063 my $ParamTypeId = getTreeAttr_Type($ParamInfoId);
5064 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId));
5065 if(not $ParamName)
5066 { # unnamed
5067 $ParamName = "p".($Pos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005068 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005069 if(defined $MissedTypedef{$Version}{$ParamTypeId})
5070 {
5071 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) {
5072 $ParamTypeId = $AddedTid;
5073 }
5074 }
5075 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005076 if(not $PType or $PType eq "Unknown") {
5077 return 1;
5078 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005079 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005080 if(not $PTName) {
5081 return 1;
5082 }
5083 if($PTName eq "void") {
5084 last;
5085 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005086 if($ParamName eq "__vtt_parm"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005087 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005088 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005089 $Vtt_Pos = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005090 $ParamInfoId = getNextElem($ParamInfoId);
5091 next;
5092 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005093 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5094 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005095 if(my $Algn = getAlgn($ParamInfoId)) {
5096 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
5097 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005098 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"}) {
5099 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($Pos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005100 }
5101 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /)
5102 { # foo(register type arg)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005103 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005104 }
5105 $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005106 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005107 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005108 if(setFuncArgs($InfoId, $Vtt_Pos)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005109 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = "-1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005110 }
5111 return 0;
5112}
5113
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005114sub setFuncArgs($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005115{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005116 my ($InfoId, $Vtt_Pos) = @_;
5117 my $FuncTypeId = getFuncTypeId($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005118 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005119 if(getFuncType($InfoId) eq "Method") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005120 $ParamListElemId = getNextElem($ParamListElemId);
5121 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005122 if(not $ParamListElemId)
5123 { # foo(...)
5124 return 1;
5125 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005126 my $HaveVoid = 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005127 my $Pos = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005128 while($ParamListElemId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005129 { # actual params: may differ from formal args
5130 # formal int*const
5131 # actual: int*
5132 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005133 {
5134 $Vtt_Pos=-1;
5135 $ParamListElemId = getNextElem($ParamListElemId);
5136 next;
5137 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005138 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId);
5139 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005140 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005141 $HaveVoid = 1;
5142 last;
5143 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005144 elsif(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005145 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005146 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005147 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5148 { # unnamed
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005149 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($Pos+1);
5150 }
5151 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005152 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005153 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005154 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5155 {
5156 my $Val = getInitVal($PurpId, $ParamTypeId);
5157 if(defined $Val) {
5158 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5159 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005160 }
5161 }
5162 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005163 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005164 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005165 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005166}
5167
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005168sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005169{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005170 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5171 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005172 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5173 return $1;
5174 }
5175 }
5176 return "";
5177}
5178
5179sub getTreeAttr_Chain($)
5180{
5181 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5182 {
5183 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5184 return $1;
5185 }
5186 }
5187 return "";
5188}
5189
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005190sub getTreeAttr_Unql($)
5191{
5192 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5193 {
5194 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5195 return $1;
5196 }
5197 }
5198 return "";
5199}
5200
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005201sub getTreeAttr_Scpe($)
5202{
5203 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5204 {
5205 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5206 return $1;
5207 }
5208 }
5209 return "";
5210}
5211
5212sub getTreeAttr_Type($)
5213{
5214 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5215 {
5216 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5217 return $1;
5218 }
5219 }
5220 return "";
5221}
5222
5223sub getTreeAttr_Name($)
5224{
5225 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5226 {
5227 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5228 return $1;
5229 }
5230 }
5231 return "";
5232}
5233
5234sub getTreeAttr_Mngl($)
5235{
5236 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5237 {
5238 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5239 return $1;
5240 }
5241 }
5242 return "";
5243}
5244
5245sub getTreeAttr_Prms($)
5246{
5247 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5248 {
5249 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5250 return $1;
5251 }
5252 }
5253 return "";
5254}
5255
5256sub getTreeAttr_Fncs($)
5257{
5258 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5259 {
5260 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5261 return $1;
5262 }
5263 }
5264 return "";
5265}
5266
5267sub getTreeAttr_Csts($)
5268{
5269 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5270 {
5271 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5272 return $1;
5273 }
5274 }
5275 return "";
5276}
5277
5278sub getTreeAttr_Purp($)
5279{
5280 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5281 {
5282 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5283 return $1;
5284 }
5285 }
5286 return "";
5287}
5288
5289sub getTreeAttr_Valu($)
5290{
5291 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5292 {
5293 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5294 return $1;
5295 }
5296 }
5297 return "";
5298}
5299
5300sub getTreeAttr_Flds($)
5301{
5302 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5303 {
5304 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5305 return $1;
5306 }
5307 }
5308 return "";
5309}
5310
5311sub getTreeAttr_Args($)
5312{
5313 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5314 {
5315 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005316 return $1;
5317 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005318 }
5319 return "";
5320}
5321
5322sub getTreeValue($)
5323{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005324 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5325 {
5326 if($Info=~/low[ ]*:[ ]*([^ ]+) /) {
5327 return $1;
5328 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005329 }
5330 return "";
5331}
5332
5333sub getTreeAccess($)
5334{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005335 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005336 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005337 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5338 {
5339 my $Access = $1;
5340 if($Access eq "prot") {
5341 return "protected";
5342 }
5343 elsif($Access eq "priv") {
5344 return "private";
5345 }
5346 }
5347 elsif($Info=~/ protected /)
5348 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005349 return "protected";
5350 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005351 elsif($Info=~/ private /)
5352 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005353 return "private";
5354 }
5355 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005356 return "public";
5357}
5358
5359sub setFuncAccess($)
5360{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005361 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005362 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005363 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005364 }
5365 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005366 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005367 }
5368}
5369
5370sub setTypeAccess($$)
5371{
5372 my ($TypeId, $TypeAttr) = @_;
5373 my $Access = getTreeAccess($TypeId);
5374 if($Access eq "protected") {
5375 $TypeAttr->{"Protected"} = 1;
5376 }
5377 elsif($Access eq "private") {
5378 $TypeAttr->{"Private"} = 1;
5379 }
5380}
5381
5382sub setFuncKind($)
5383{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005384 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5385 {
5386 if($Info=~/pseudo tmpl/) {
5387 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
5388 }
5389 elsif($Info=~/ constructor /) {
5390 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
5391 }
5392 elsif($Info=~/ destructor /) {
5393 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
5394 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005395 }
5396}
5397
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005398sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005399{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005400 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5401 {
5402 if($Info=~/spec[ ]*:[ ]*pure /) {
5403 return "PureVirt";
5404 }
5405 elsif($Info=~/spec[ ]*:[ ]*virt /) {
5406 return "Virt";
5407 }
5408 elsif($Info=~/ pure\s+virtual /)
5409 { # support for old GCC versions
5410 return "PureVirt";
5411 }
5412 elsif($Info=~/ virtual /)
5413 { # support for old GCC versions
5414 return "Virt";
5415 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005416 }
5417 return "";
5418}
5419
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005420sub getFuncLink($)
5421{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005422 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5423 {
5424 if($Info=~/link[ ]*:[ ]*static /) {
5425 return "Static";
5426 }
5427 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005428 return $1;
5429 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005430 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005431 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005432}
5433
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005434sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005435{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005436 my ($Symbol, $LibVersion) = @_;
5437 return "" if(not $Symbol or not $LibVersion);
5438 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
5439 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005440 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005441 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
5442 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
5443 }
5444 }
5445 if($NS)
5446 {
5447 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5448 return $NS;
5449 }
5450 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005451 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005452 while($NS=~s/::[^:]+\Z//)
5453 {
5454 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5455 return $NS;
5456 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005457 }
5458 }
5459 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005460
5461 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005462}
5463
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005464sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005465{
5466 my ($TypeName, $LibVersion) = @_;
5467 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005468 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005469 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005470 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5471 return $NS;
5472 }
5473 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005474 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005475 while($NS=~s/::[^:]+\Z//)
5476 {
5477 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5478 return $NS;
5479 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005480 }
5481 }
5482 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005483 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005484}
5485
5486sub getNameSpace($)
5487{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005488 my $InfoId = $_[0];
5489 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005490 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005491 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005492 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005493 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005494 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005495 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
5496 {
5497 my $NameSpace = getTreeStr($1);
5498 if($NameSpace eq "::")
5499 { # global namespace
5500 return "";
5501 }
5502 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
5503 $NameSpace = $BaseNameSpace."::".$NameSpace;
5504 }
5505 $NestedNameSpaces{$Version}{$NameSpace} = 1;
5506 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005507 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005508 else {
5509 return "";
5510 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005511 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005512 elsif($InfoType eq "record_type")
5513 { # inside data type
5514 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
5515 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005516 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005517 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005518 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005519 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005520}
5521
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005522sub getEnumMembVal($)
5523{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005524 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005525 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005526 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
5527 {
5528 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
5529 {
5530 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
5531 { # in newer versions of GCC the value is in the "const_decl->cnst" node
5532 return getTreeValue($1);
5533 }
5534 else
5535 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
5536 return getTreeValue($1);
5537 }
5538 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005539 }
5540 }
5541 return "";
5542}
5543
5544sub getSize($)
5545{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005546 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5547 {
5548 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
5549 return getTreeValue($1);
5550 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005551 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005552 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005553}
5554
5555sub getAlgn($)
5556{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005557 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5558 {
5559 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
5560 return $1;
5561 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005562 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005563 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005564}
5565
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005566sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005567{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005568 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5569 {
5570 if($Info=~/ bitfield /) {
5571 return getSize($_[0]);
5572 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005573 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005574 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005575}
5576
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005577sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005578{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005579 if(my $Chan = getTreeAttr_Chan($_[0])) {
5580 return $Chan;
5581 }
5582 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
5583 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005584 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005585 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005586}
5587
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005588sub registerHeader($$)
5589{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005590 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005591 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005592 return "";
5593 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005594 if(is_abs($Header) and not -f $Header)
5595 { # incorrect absolute path
5596 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005597 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005598 if(skipHeader($Header, $LibVersion))
5599 { # skip
5600 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005601 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005602 if(my $Header_Path = identifyHeader($Header, $LibVersion))
5603 {
5604 detect_header_includes($Header_Path, $LibVersion);
5605
5606 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
5607 { # redirect
5608 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
5609 or skipHeader($RHeader_Path, $LibVersion))
5610 { # skip
5611 return "";
5612 }
5613 $Header_Path = $RHeader_Path;
5614 }
5615 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
5616 { # skip
5617 return "";
5618 }
5619
5620 if(my $HName = get_filename($Header_Path))
5621 { # register
5622 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
5623 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
5624 }
5625
5626 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
5627 or $Header!~/\.(\w+)\Z/)
5628 { # hpp, hh
5629 setLanguage($LibVersion, "C++");
5630 }
5631
5632 if($CheckHeadersOnly
5633 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
5634 { # /usr/include/c++/4.6.1/...
5635 $STDCXX_TESTING = 1;
5636 }
5637
5638 return $Header_Path;
5639 }
5640 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005641}
5642
5643sub register_directory($$$)
5644{
5645 my ($Dir, $WithDeps, $LibVersion) = @_;
5646 $Dir=~s/[\/\\]+\Z//g;
5647 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005648 $Dir = get_abs_path($Dir);
5649 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005650 if($WithDeps)
5651 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005652 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
5653 return;
5654 }
5655 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
5656 $Mode = "DepsOnly";
5657 }
5658 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005659 else
5660 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005661 if($RegisteredDirs{$LibVersion}{$Dir}{1}
5662 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
5663 return;
5664 }
5665 }
5666 $Header_Dependency{$LibVersion}{$Dir} = 1;
5667 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
5668 if($Mode eq "DepsOnly")
5669 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005670 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005671 $Header_Dependency{$LibVersion}{$Path} = 1;
5672 }
5673 return;
5674 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005675 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005676 {
5677 if($WithDeps)
5678 {
5679 my $SubDir = $Path;
5680 while(($SubDir = get_dirname($SubDir)) ne $Dir)
5681 { # register all sub directories
5682 $Header_Dependency{$LibVersion}{$SubDir} = 1;
5683 }
5684 }
5685 next if(is_not_header($Path));
5686 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005687 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005688 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005689 $Include_Neighbors{$LibVersion}{$Part} = $Path;
5690 }
5691 }
5692 if(get_filename($Dir) eq "include")
5693 { # search for "lib/include/" directory
5694 my $LibDir = $Dir;
5695 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
5696 register_directory($LibDir, $WithDeps, $LibVersion);
5697 }
5698 }
5699}
5700
5701sub parse_redirect($$$)
5702{
5703 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005704 my @Errors = ();
5705 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
5706 push(@Errors, $1);
5707 }
5708 my $Redirect = "";
5709 foreach (@Errors)
5710 {
5711 s/\s{2,}/ /g;
5712 if(/(only|must\ include
5713 |update\ to\ include
5714 |replaced\ with
5715 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005716 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005717 {
5718 $Redirect = $2;
5719 last;
5720 }
5721 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
5722 {
5723 $Redirect = $2;
5724 last;
5725 }
5726 elsif(/this\ header\ should\ not\ be\ used
5727 |programs\ should\ not\ directly\ include
5728 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
5729 |is\ not\ supported\ API\ for\ general\ use
5730 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005731 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005732 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
5733 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
5734 }
5735 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005736 if($Redirect)
5737 {
5738 $Redirect=~s/\A<//g;
5739 $Redirect=~s/>\Z//g;
5740 }
5741 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005742}
5743
5744sub parse_includes($$)
5745{
5746 my ($Content, $Path) = @_;
5747 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005748 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005749 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005750 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005751 my $Method = substr($Header, 0, 1, "");
5752 substr($Header, length($Header)-1, 1, "");
5753 $Header = path_format($Header, $OSgroup);
5754 if($Method eq "\"" or is_abs($Header))
5755 {
5756 if(-e join_P(get_dirname($Path), $Header))
5757 { # relative path exists
5758 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005759 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005760 else
5761 { # include "..." that doesn't exist is equal to include <...>
5762 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005763 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005764 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005765 else {
5766 $Includes{$Header} = 1;
5767 }
5768 }
5769 if($ExtraInfo)
5770 {
5771 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
5772 { # FT_FREETYPE_H
5773 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005774 }
5775 }
5776 return \%Includes;
5777}
5778
5779sub ignore_path($)
5780{
5781 my $Path = $_[0];
5782 if($Path=~/\~\Z/)
5783 {# skipping system backup files
5784 return 1;
5785 }
5786 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
5787 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
5788 return 1;
5789 }
5790 return 0;
5791}
5792
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005793sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005794{
5795 my ($ArrRef, $W) = @_;
5796 return if(length($W)<2);
5797 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
5798}
5799
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005800sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005801{
5802 my ($H1, $H2) = @_;
5803 $H1=~s/\.[a-z]+\Z//ig;
5804 $H2=~s/\.[a-z]+\Z//ig;
5805 my ($HDir1, $Hname1) = separate_path($H1);
5806 my ($HDir2, $Hname2) = separate_path($H2);
5807 my $Dirname1 = get_filename($HDir1);
5808 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005809 if($_[0] eq $_[1]
5810 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005811 return 0;
5812 }
5813 elsif($H1=~/\A\Q$H2\E/) {
5814 return 1;
5815 }
5816 elsif($H2=~/\A\Q$H1\E/) {
5817 return -1;
5818 }
5819 elsif($HDir1=~/\Q$Hname1\E/i
5820 and $HDir2!~/\Q$Hname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005821 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005822 return -1;
5823 }
5824 elsif($HDir2=~/\Q$Hname2\E/i
5825 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005826 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005827 return 1;
5828 }
5829 elsif($Hname1=~/\Q$Dirname1\E/i
5830 and $Hname2!~/\Q$Dirname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005831 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005832 return -1;
5833 }
5834 elsif($Hname2=~/\Q$Dirname2\E/i
5835 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005836 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005837 return 1;
5838 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005839 elsif($Hname1=~/(config|lib|util)/i
5840 and $Hname2!~/(config|lib|util)/i)
5841 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005842 return -1;
5843 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005844 elsif($Hname2=~/(config|lib|util)/i
5845 and $Hname1!~/(config|lib|util)/i)
5846 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005847 return 1;
5848 }
5849 elsif(checkRelevance($H1)
5850 and not checkRelevance($H2))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005851 { # libebook/e-book.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005852 return -1;
5853 }
5854 elsif(checkRelevance($H2)
5855 and not checkRelevance($H1))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005856 { # libebook/e-book.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005857 return 1;
5858 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005859 else
5860 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005861 return (lc($H1) cmp lc($H2));
5862 }
5863}
5864
5865sub searchForHeaders($)
5866{
5867 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005868
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005869 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005870 registerGccHeaders();
5871
5872 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
5873 { # c++ standard include paths
5874 registerCppHeaders();
5875 }
5876
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005877 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005878 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
5879 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005880 {
5881 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005882 if($SystemRoot)
5883 {
5884 if(is_abs($Path)) {
5885 $Path = $SystemRoot.$Path;
5886 }
5887 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005888 if(not -e $Path) {
5889 exitStatus("Access_Error", "can't access \'$Path\'");
5890 }
5891 elsif(-f $Path) {
5892 exitStatus("Access_Error", "\'$Path\' - not a directory");
5893 }
5894 elsif(-d $Path)
5895 {
5896 $Path = get_abs_path($Path);
5897 register_directory($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005898 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
5899 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005900 }
5901 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005902 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005903 }
5904 }
5905 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005906 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005907 $INC_PATH_AUTODETECT{$LibVersion} = 0;
5908 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005909
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005910 # registering directories
5911 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
5912 {
5913 next if(not -e $Path);
5914 $Path = get_abs_path($Path);
5915 $Path = path_format($Path, $OSgroup);
5916 if(-d $Path) {
5917 register_directory($Path, 1, $LibVersion);
5918 }
5919 elsif(-f $Path)
5920 {
5921 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005922 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005923 and not $LocalIncludes{$Dir})
5924 {
5925 register_directory($Dir, 1, $LibVersion);
5926 if(my $OutDir = get_dirname($Dir))
5927 { # registering the outer directory
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005928 if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005929 and not $LocalIncludes{$OutDir}) {
5930 register_directory($OutDir, 0, $LibVersion);
5931 }
5932 }
5933 }
5934 }
5935 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005936
5937 # clean memory
5938 %RegisteredDirs = ();
5939
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005940 # registering headers
5941 my $Position = 0;
5942 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
5943 {
5944 if(is_abs($Dest) and not -e $Dest) {
5945 exitStatus("Access_Error", "can't access \'$Dest\'");
5946 }
5947 $Dest = path_format($Dest, $OSgroup);
5948 if(is_header($Dest, 1, $LibVersion))
5949 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005950 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005951 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
5952 }
5953 }
5954 elsif(-d $Dest)
5955 {
5956 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005957 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005958 {
5959 next if(ignore_path($Path));
5960 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005961 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005962 push(@Registered, $HPath);
5963 }
5964 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005965 @Registered = sort {sortHeaders($a, $b)} @Registered;
5966 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005967 foreach my $Path (@Registered) {
5968 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
5969 }
5970 }
5971 else {
5972 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
5973 }
5974 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005975 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
5976 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005977 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005978 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005979 if(is_abs($Header) and not -f $Header) {
5980 exitStatus("Access_Error", "can't access file \'$Header\'");
5981 }
5982 $Header = path_format($Header, $OSgroup);
5983 if(my $Header_Path = is_header($Header, 1, $LibVersion))
5984 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005985 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005986 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005987 }
5988 else {
5989 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
5990 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005991 }
5992 }
5993 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
5994 { # set relative paths (for duplicates)
5995 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
5996 { # search for duplicates
5997 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
5998 my $Prefix = get_dirname($FirstPath);
5999 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6000 { # detect a shortest distinguishing prefix
6001 my $NewPrefix = $1;
6002 my %Identity = ();
6003 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6004 {
6005 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6006 $Identity{$Path} = $1;
6007 }
6008 }
6009 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6010 { # all names are differend with current prefix
6011 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6012 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6013 }
6014 last;
6015 }
6016 $Prefix = $NewPrefix; # increase prefix
6017 }
6018 }
6019 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006020
6021 # clean memory
6022 %HeaderName_Paths = ();
6023
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006024 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6025 { # ordering headers according to descriptor
6026 my $PairName=$Include_Order{$LibVersion}{$HeaderName};
6027 my ($Pos, $PairPos) = (-1, -1);
6028 my ($Path, $PairPath) = ();
6029 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6030 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6031 foreach my $Header_Path (@Paths)
6032 {
6033 if(get_filename($Header_Path) eq $PairName)
6034 {
6035 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6036 $PairPath = $Header_Path;
6037 }
6038 if(get_filename($Header_Path) eq $HeaderName)
6039 {
6040 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6041 $Path = $Header_Path;
6042 }
6043 }
6044 if($PairPos!=-1 and $Pos!=-1
6045 and int($PairPos)<int($Pos))
6046 {
6047 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6048 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6049 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6050 }
6051 }
6052 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6053 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6054 }
6055}
6056
6057sub detect_real_includes($$)
6058{
6059 my ($AbsPath, $LibVersion) = @_;
6060 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6061 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6062 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6063 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6064 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006065 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6066
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006067 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6068 return () if(not $Path);
6069 open(PREPROC, $Path);
6070 while(<PREPROC>)
6071 {
6072 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6073 {
6074 my $Include = path_format($1, $OSgroup);
6075 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6076 next;
6077 }
6078 if($Include eq $AbsPath) {
6079 next;
6080 }
6081 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6082 }
6083 }
6084 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006085 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6086}
6087
6088sub detect_header_includes($$)
6089{
6090 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006091 return if(not $LibVersion or not $Path);
6092 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6093 return;
6094 }
6095 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6096
6097 if(not -e $Path) {
6098 return;
6099 }
6100
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006101 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006102 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6103 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006104 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006105 {
6106 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006107 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006108 }
6109 if($RedirectPath ne $Path) {
6110 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6111 }
6112 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006113 else
6114 { # can't find
6115 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6116 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006117 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006118 if(my $Inc = parse_includes($Content, $Path))
6119 {
6120 foreach my $Include (keys(%{$Inc}))
6121 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006122 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
6123 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006124 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006125}
6126
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006127sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006128{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006129 my $Path = $_[0];
6130 my ($Dir, $Name) = separate_path($Path);
6131 if(get_filename($Dir)=~/\A(include|libc)\Z/ and $GlibcHeader{$Name})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006132 { # /usr/include/{stdio, ...}.h
6133 # epoc32/include/libc/{stdio, ...}.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006134 return 1;
6135 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006136 return 0;
6137}
6138
6139sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006140{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006141 my $Dir = $_[0];
6142 my ($OutDir, $Name) = separate_path($Dir);
6143 if(get_filename($OutDir)=~/\A(include|libc)\Z/
6144 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6145 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6146 return 1;
6147 }
6148 return 0;
6149}
6150
6151sub detect_recursive_includes($$)
6152{
6153 my ($AbsPath, $LibVersion) = @_;
6154 return () if(not $AbsPath);
6155 if(isCyclical(\@RecurInclude, $AbsPath)) {
6156 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6157 }
6158 my ($AbsDir, $Name) = separate_path($AbsPath);
6159 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006160 { # system GLIBC internals
6161 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006162 }
6163 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6164 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6165 }
6166 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006167
6168 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6169 { # skip /usr/include/c++/*/ headers
6170 return () if(not $ExtraInfo);
6171 }
6172
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006173 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006174 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006175 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006176 { # check "real" (non-"model") include paths
6177 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6178 pop(@RecurInclude);
6179 return @Paths;
6180 }
6181 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6182 detect_header_includes($AbsPath, $LibVersion);
6183 }
6184 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6185 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006186 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006187 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006188 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006189 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006190 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006191 if(-f $Candidate) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006192 $HPath = realpath($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006193 }
6194 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006195 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006196 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006197 { # search for the nearest header
6198 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006199 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006200 if(-f $Candidate) {
6201 $HPath = $Candidate;
6202 }
6203 }
6204 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006205 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006206 }
6207 next if(not $HPath);
6208 if($HPath eq $AbsPath) {
6209 next;
6210 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006211
6212 if($Debug)
6213 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006214# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6215# {
6216# print STDERR "$AbsPath -> $HPath\n";
6217# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006218 }
6219
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006220 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6221 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006222 { # only include <...>, skip include "..." prefixes
6223 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6224 }
6225 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6226 {
6227 if($IncPath eq $AbsPath) {
6228 next;
6229 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006230 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6231 if($RIncType==-1)
6232 { # include "..."
6233 $RIncType = $IncType;
6234 }
6235 elsif($RIncType==2)
6236 {
6237 if($IncType!=-1) {
6238 $RIncType = $IncType;
6239 }
6240 }
6241 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006242 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6243 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6244 }
6245 }
6246 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6247 {
6248 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6249 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6250 { # distinguish math.h from glibc and math.h from the tested library
6251 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6252 last;
6253 }
6254 }
6255 }
6256 pop(@RecurInclude);
6257 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6258}
6259
6260sub find_in_framework($$$)
6261{
6262 my ($Header, $Framework, $LibVersion) = @_;
6263 return "" if(not $Header or not $Framework or not $LibVersion);
6264 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6265 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6266 }
6267 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6268 {
6269 if(get_filename($Dependency) eq $Framework
6270 and -f get_dirname($Dependency)."/".$Header) {
6271 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6272 }
6273 }
6274 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6275}
6276
6277sub find_in_defaults($)
6278{
6279 my $Header = $_[0];
6280 return "" if(not $Header);
6281 if(defined $Cache{"find_in_defaults"}{$Header}) {
6282 return $Cache{"find_in_defaults"}{$Header};
6283 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006284 foreach my $Dir (@DefaultIncPaths,
6285 @DefaultGccPaths,
6286 @DefaultCppPaths,
6287 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006288 {
6289 next if(not $Dir);
6290 if(-f $Dir."/".$Header) {
6291 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
6292 }
6293 }
6294 return ($Cache{"find_in_defaults"}{$Header}="");
6295}
6296
6297sub cmp_paths($$)
6298{
6299 my ($Path1, $Path2) = @_;
6300 my @Parts1 = split(/[\/\\]/, $Path1);
6301 my @Parts2 = split(/[\/\\]/, $Path2);
6302 foreach my $Num (0 .. $#Parts1)
6303 {
6304 my $Part1 = $Parts1[$Num];
6305 my $Part2 = $Parts2[$Num];
6306 if($GlibcDir{$Part1}
6307 and not $GlibcDir{$Part2}) {
6308 return 1;
6309 }
6310 elsif($GlibcDir{$Part2}
6311 and not $GlibcDir{$Part1}) {
6312 return -1;
6313 }
6314 elsif($Part1=~/glib/
6315 and $Part2!~/glib/) {
6316 return 1;
6317 }
6318 elsif($Part1!~/glib/
6319 and $Part2=~/glib/) {
6320 return -1;
6321 }
6322 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
6323 return $CmpRes;
6324 }
6325 }
6326 return 0;
6327}
6328
6329sub checkRelevance($)
6330{
6331 my ($Path) = @_;
6332 return 0 if(not $Path);
6333 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006334 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006335 }
6336 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006337 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006338 my @Tokens = split(/[_\d\W]+/, $Name);
6339 foreach (@Tokens)
6340 {
6341 next if(not $_);
6342 if($Dir=~/(\A|lib|[_\d\W])\Q$_\E([_\d\W]|lib|\Z)/i
6343 or length($_)>=4 and $Dir=~/\Q$_\E/i)
6344 { # include/gupnp-1.0/libgupnp/gupnp-context.h
6345 # include/evolution-data-server-1.4/libebook/e-book.h
6346 return 1;
6347 }
6348 }
6349 return 0;
6350}
6351
6352sub checkFamily(@)
6353{
6354 my @Paths = @_;
6355 return 1 if($#Paths<=0);
6356 my %Prefix = ();
6357 foreach my $Path (@Paths)
6358 {
6359 if($SystemRoot) {
6360 $Path = cut_path_prefix($Path, $SystemRoot);
6361 }
6362 if(my $Dir = get_dirname($Path))
6363 {
6364 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
6365 $Prefix{$Dir} += 1;
6366 $Prefix{get_dirname($Dir)} += 1;
6367 }
6368 }
6369 foreach (sort keys(%Prefix))
6370 {
6371 if(get_depth($_)>=3
6372 and $Prefix{$_}==$#Paths+1) {
6373 return 1;
6374 }
6375 }
6376 return 0;
6377}
6378
6379sub isAcceptable($$$)
6380{
6381 my ($Header, $Candidate, $LibVersion) = @_;
6382 my $HName = get_filename($Header);
6383 if(get_dirname($Header))
6384 { # with prefix
6385 return 1;
6386 }
6387 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
6388 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
6389 return 1;
6390 }
6391 if(checkRelevance($Candidate))
6392 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
6393 return 1;
6394 }
6395 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
6396 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
6397 # /usr/include/qt4/Qt/qsslconfiguration.h
6398 return 1;
6399 }
6400 if($OStarget eq "symbian")
6401 {
6402 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
6403 return 1;
6404 }
6405 }
6406 return 0;
6407}
6408
6409sub isRelevant($$$)
6410{ # disallow to search for "abstract" headers in too deep directories
6411 my ($Header, $Candidate, $LibVersion) = @_;
6412 my $HName = get_filename($Header);
6413 if($OStarget eq "symbian")
6414 {
6415 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
6416 return 0;
6417 }
6418 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006419 if($OStarget ne "bsd")
6420 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006421 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
6422 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
6423 return 0;
6424 }
6425 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006426 if($OStarget ne "windows")
6427 {
6428 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
6429 { # skip /usr/include/wine/msvcrt
6430 return 0;
6431 }
6432 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006433 if(not get_dirname($Header)
6434 and $Candidate=~/[\/\\]wx[\/\\]/)
6435 { # do NOT search in system /wx/ directory
6436 # for headers without a prefix: sstream.h
6437 return 0;
6438 }
6439 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
6440 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
6441 { # skip ../c++/3.3.3/ if using ../c++/4.5/
6442 return 0;
6443 }
6444 if($Candidate=~/[\/\\]asm-/
6445 and (my $Arch = getArch($LibVersion)) ne "unknown")
6446 { # arch-specific header files
6447 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
6448 {# skip ../asm-arm/ if using x86 architecture
6449 return 0;
6450 }
6451 }
6452 my @Candidates = getSystemHeaders($HName, $LibVersion);
6453 if($#Candidates==1)
6454 { # unique header
6455 return 1;
6456 }
6457 my @SCandidates = getSystemHeaders($Header, $LibVersion);
6458 if($#SCandidates==1)
6459 { # unique name
6460 return 1;
6461 }
6462 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
6463 if(get_depth($Candidate)-$SystemDepth>=5)
6464 { # abstract headers in too deep directories
6465 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
6466 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
6467 return 0;
6468 }
6469 }
6470 if($Header eq "parser.h"
6471 and $Candidate!~/\/libxml2\//)
6472 { # select parser.h from xml2 library
6473 return 0;
6474 }
6475 if(not get_dirname($Header)
6476 and keys(%{$SystemHeaders{$HName}})>=3)
6477 { # many headers with the same name
6478 # like thread.h included without a prefix
6479 if(not checkFamily(@Candidates)) {
6480 return 0;
6481 }
6482 }
6483 return 1;
6484}
6485
6486sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006487{ # cache function
6488 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
6489 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
6490 }
6491 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
6492}
6493
6494sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006495{
6496 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006497 if(-f $Header) {
6498 return $Header;
6499 }
6500 if(is_abs($Header) and not -f $Header)
6501 { # incorrect absolute path
6502 return "";
6503 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006504 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006505 { # too abstract configuration headers
6506 return "";
6507 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006508 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006509 if($OSgroup ne "windows")
6510 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006511 if(defined $WinHeaders{lc($HName)}
6512 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006513 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006514 return "";
6515 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006516 }
6517 if($OSgroup ne "macos")
6518 {
6519 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006520 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006521 return "";
6522 }
6523 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006524
6525 if(defined $ObsoleteHeaders{$HName})
6526 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006527 return "";
6528 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006529 if($OSgroup eq "linux" or $OSgroup eq "bsd")
6530 {
6531 if(defined $AlienHeaders{$HName}
6532 or defined $AlienHeaders{$Header})
6533 { # alien headers from other systems
6534 return "";
6535 }
6536 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006537
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006538 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006539 { # search in default paths
6540 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006541 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006542 }
6543 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006544 if(not keys(%SystemHeaders))
6545 { # register all headers in system include dirs
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006546 detectSystemHeaders();
6547 }
6548 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
6549 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
6550 {
6551 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006552 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006553 }
6554 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006555 # error
6556 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006557}
6558
6559sub getSystemHeaders($$)
6560{
6561 my ($Header, $LibVersion) = @_;
6562 my @Candidates = ();
6563 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
6564 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006565 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006566 next;
6567 }
6568 push(@Candidates, $Candidate);
6569 }
6570 return @Candidates;
6571}
6572
6573sub cut_path_prefix($$)
6574{
6575 my ($Path, $Prefix) = @_;
6576 return $Path if(not $Prefix);
6577 $Prefix=~s/[\/\\]+\Z//;
6578 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
6579 return $Path;
6580}
6581
6582sub is_default_include_dir($)
6583{
6584 my $Dir = $_[0];
6585 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006586 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006587}
6588
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006589sub identifyHeader($$)
6590{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006591 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006592 if(not $Header) {
6593 return "";
6594 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006595 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006596 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
6597 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006598 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006599 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006600}
6601
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006602sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006603{ # search for header by absolute path, relative path or name
6604 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006605 if(-f $Header)
6606 { # it's relative or absolute path
6607 return get_abs_path($Header);
6608 }
6609 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
6610 and my $HeaderDir = find_in_defaults($Header))
6611 { # search for libc headers in the /usr/include
6612 # for non-libc target library before searching
6613 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006614 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006615 }
6616 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
6617 { # search in the target library paths
6618 return $Path;
6619 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006620 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006621 { # search in the internal GCC include paths
6622 return $DefaultGccHeader{$Header};
6623 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006624 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006625 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006626 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006627 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006628 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006629 { # search in the default G++ include paths
6630 return $DefaultCppHeader{$Header};
6631 }
6632 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
6633 { # search everywhere in the system
6634 return $AnyPath;
6635 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006636 elsif($OSgroup eq "macos")
6637 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
6638 if(my $Dir = get_dirname($Header))
6639 {
6640 my $RelPath = "Headers\/".get_filename($Header);
6641 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006642 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006643 }
6644 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006645 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006646 # cannot find anything
6647 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006648}
6649
6650sub getLocation($)
6651{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006652 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6653 {
6654 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006655 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006656 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006657 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006658 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006659}
6660
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006661sub getNameByInfo($)
6662{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006663 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006664 {
6665 if($Info=~/name[ ]*:[ ]*@(\d+) /)
6666 {
6667 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
6668 {
6669 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
6670 { # short unsigned int (may include spaces)
6671 return $1;
6672 }
6673 }
6674 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006675 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006676 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006677}
6678
6679sub getTreeStr($)
6680{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006681 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006682 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006683 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
6684 {
6685 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04006686 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006687 and $Str=~/\Ac99_(.+)\Z/)
6688 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006689 if($CppKeywords_A{$1}) {
6690 $Str=$1;
6691 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006692 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006693 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006694 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006695 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006696 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006697}
6698
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006699sub getFuncShortName($)
6700{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006701 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006702 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006703 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006704 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006705 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006706 {
6707 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
6708 {
6709 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
6710 return "operator ".$RName;
6711 }
6712 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006713 }
6714 else
6715 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006716 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
6717 {
6718 if(my $Ind = $Operator_Indication{$1}) {
6719 return "operator".$Ind;
6720 }
6721 elsif(not $UnknownOperator{$1})
6722 {
6723 printMsg("WARNING", "unknown operator $1");
6724 $UnknownOperator{$1} = 1;
6725 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006726 }
6727 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006728 }
6729 else
6730 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006731 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
6732 return getTreeStr($1);
6733 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006734 }
6735 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006736 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006737}
6738
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006739sub getFuncReturn($)
6740{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006741 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6742 {
6743 if($Info=~/type[ ]*:[ ]*@(\d+) /)
6744 {
6745 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
6746 return $1;
6747 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006748 }
6749 }
6750 return "";
6751}
6752
6753sub getFuncOrig($)
6754{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006755 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6756 {
6757 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
6758 return $1;
6759 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006760 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006761 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006762}
6763
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006764sub unmangleArray(@)
6765{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006766 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006767 { # MSVC mangling
6768 my $UndNameCmd = get_CmdPath("undname");
6769 if(not $UndNameCmd) {
6770 exitStatus("Not_Found", "can't find \"undname\"");
6771 }
6772 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006773 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006774 }
6775 else
6776 { # GCC mangling
6777 my $CppFiltCmd = get_CmdPath("c++filt");
6778 if(not $CppFiltCmd) {
6779 exitStatus("Not_Found", "can't find c++filt in PATH");
6780 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006781 if(not defined $CPPFILT_SUPPORT_FILE)
6782 {
6783 my $Info = `$CppFiltCmd -h 2>&1`;
6784 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
6785 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006786 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006787 if($CPPFILT_SUPPORT_FILE)
6788 { # new versions of c++filt can take a file
6789 if($#_>$MAX_CPPFILT_FILE_SIZE)
6790 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
6791 # this is fixed in the oncoming version of Binutils
6792 my @Half = splice(@_, 0, ($#_+1)/2);
6793 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006794 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006795 else
6796 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006797 writeFile("$TMP_DIR/unmangle", join("\n", @_));
6798 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
6799 if($?==139)
6800 { # segmentation fault
6801 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
6802 }
6803 return split(/\n/, $Res);
6804 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006805 }
6806 else
6807 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006808 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
6809 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006810 my @Half = splice(@_, 0, ($#_+1)/2);
6811 return (unmangleArray(@Half), unmangleArray(@_))
6812 }
6813 else
6814 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006815 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006816 my $Res = `$CppFiltCmd $NoStrip $Strings`;
6817 if($?==139)
6818 { # segmentation fault
6819 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
6820 }
6821 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006822 }
6823 }
6824 }
6825}
6826
6827sub get_SignatureNoInfo($$)
6828{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006829 my ($Symbol, $LibVersion) = @_;
6830 if($Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol}) {
6831 return $Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006832 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006833 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006834 my $Signature = $tr_name{$MnglName}?$tr_name{$MnglName}:$MnglName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006835 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006836 { # C++
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04006837 # some standard typedefs
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006838 $Signature=~s/\Qstd::basic_string<char, std::char_traits<char>, std::allocator<char> >\E/std::string/g;
6839 $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;
6840 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04006841 if(not $CheckObjectsOnly or $OSgroup=~/linux|bsd|beos/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006842 { # ELF format marks data as OBJECT
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006843 if($GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006844 $Signature .= " [data]";
6845 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006846 elsif($Symbol!~/\A(_Z|\?)/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006847 $Signature .= " (...)";
6848 }
6849 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006850 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006851 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04006852 my $ShortName = substr($Signature, 0, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006853 $Signature=~s/\A\Q$ShortName\E/$ShortName $ChargeLevel/g;
6854 }
6855 if($SymbolVersion) {
6856 $Signature .= $VersionSpec.$SymbolVersion;
6857 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006858 return ($Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006859}
6860
6861sub get_ChargeLevel($$)
6862{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006863 my ($Symbol, $LibVersion) = @_;
6864 return "" if($Symbol!~/\A(_Z|\?)/);
6865 if(defined $CompleteSignature{$LibVersion}{$Symbol}
6866 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006867 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006868 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006869 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006870 if($Symbol=~/C1E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006871 return "[in-charge]";
6872 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006873 elsif($Symbol=~/C2E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006874 return "[not-in-charge]";
6875 }
6876 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006877 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006878 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006879 if($Symbol=~/D1E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006880 return "[in-charge]";
6881 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006882 elsif($Symbol=~/D2E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006883 return "[not-in-charge]";
6884 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006885 elsif($Symbol=~/D0E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006886 return "[in-charge-deleting]";
6887 }
6888 }
6889 }
6890 else
6891 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006892 if($Symbol=~/C1E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006893 return "[in-charge]";
6894 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006895 elsif($Symbol=~/C2E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006896 return "[not-in-charge]";
6897 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006898 elsif($Symbol=~/D1E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006899 return "[in-charge]";
6900 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006901 elsif($Symbol=~/D2E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006902 return "[not-in-charge]";
6903 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006904 elsif($Symbol=~/D0E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006905 return "[in-charge-deleting]";
6906 }
6907 }
6908 return "";
6909}
6910
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04006911sub get_Signature_M($$)
6912{
6913 my ($Symbol, $LibVersion) = @_;
6914 my $Signature_M = $tr_name{$Symbol};
6915 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
6916 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006917 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04006918 }
6919 return $Signature_M;
6920}
6921
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006922sub get_Signature($$)
6923{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006924 my ($Symbol, $LibVersion) = @_;
6925 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
6926 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006927 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006928 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
6929 if(isPrivateData($MnglName) or not $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04006930 { # non-public global data
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006931 return get_SignatureNoInfo($Symbol, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006932 }
6933 my ($Func_Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006934 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
6935 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006936 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006937 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
6938 $Func_Signature = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".(($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})?"~":"").$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006939 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006940 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006941 $Func_Signature = $NameSpace."::".$ShortName;
6942 }
6943 else {
6944 $Func_Signature = $ShortName;
6945 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04006946 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
6947 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006948 }
6949 else {
6950 $Func_Signature = $MnglName;
6951 }
6952 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006953 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006954 {
6955 next if($Pos eq "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006956 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006957 next if(not $ParamTypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006958 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006959 if(not $ParamTypeName) {
6960 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
6961 }
6962 foreach my $Typedef (keys(%ChangedTypedef))
6963 {
6964 my $Base = $Typedef_BaseName{$LibVersion}{$Typedef};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006965 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006966 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006967 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006968 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
6969 }
6970 else {
6971 push(@ParamArray, $ParamTypeName);
6972 }
6973 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006974 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
6975 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006976 $Func_Signature .= " [data]";
6977 }
6978 else
6979 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006980 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006981 { # add [in-charge]
6982 $Func_Signature .= " ".$ChargeLevel;
6983 }
6984 $Func_Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006985 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
6986 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006987 $Func_Signature .= " const";
6988 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006989 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
6990 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006991 $Func_Signature .= " volatile";
6992 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006993 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
6994 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006995 { # for static methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006996 $Func_Signature .= " [static]";
6997 }
6998 }
6999 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007000 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
7001 $Func_Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007002 }
7003 if($SymbolVersion) {
7004 $Func_Signature .= $VersionSpec.$SymbolVersion;
7005 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007006 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Func_Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007007}
7008
7009sub create_member_decl($$)
7010{
7011 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007012 if($TName=~/\([\*]+\)/)
7013 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007014 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7015 return $TName;
7016 }
7017 else
7018 {
7019 my @ArraySizes = ();
7020 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7021 push(@ArraySizes, $1);
7022 }
7023 return $TName." ".$Member.join("", @ArraySizes);
7024 }
7025}
7026
7027sub getFuncType($)
7028{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007029 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7030 {
7031 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7032 {
7033 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7034 {
7035 if($Type eq "method_type") {
7036 return "Method";
7037 }
7038 elsif($Type eq "function_type") {
7039 return "Function";
7040 }
7041 else {
7042 return "Other";
7043 }
7044 }
7045 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007046 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007047 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007048}
7049
7050sub getFuncTypeId($)
7051{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007052 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7053 {
7054 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7055 return $1;
7056 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007057 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007058 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007059}
7060
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007061sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007062{ # "._N" or "$_N" in older GCC versions
7063 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007064}
7065
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007066sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007067{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007068 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7069 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007070 }
7071
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007072 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007073
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007074 if($_[1] ne "S")
7075 {
7076 $N=~s/\A[ ]+//g;
7077 $N=~s/[ ]+\Z//g;
7078 $N=~s/[ ]{2,}/ /g;
7079 }
7080
7081 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007082
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007083 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007084
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007085 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7086 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007087
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007088 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007089
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007090 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007091
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007092 if($_[1] eq "S")
7093 {
7094 if(index($N, "operator")!=-1) {
7095 $N=~s/\b(operator[ ]*)> >/$1>>/;
7096 }
7097 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007098
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007099 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007100}
7101
7102sub get_HeaderDeps($$)
7103{
7104 my ($AbsPath, $LibVersion) = @_;
7105 return () if(not $AbsPath or not $LibVersion);
7106 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7107 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7108 }
7109 my %IncDir = ();
7110 detect_recursive_includes($AbsPath, $LibVersion);
7111 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7112 {
7113 next if(not $HeaderPath);
7114 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7115 my $Dir = get_dirname($HeaderPath);
7116 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7117 {
7118 my $Dep = $Dir;
7119 if($Prefix)
7120 {
7121 if($OSgroup eq "windows")
7122 { # case insensitive seach on windows
7123 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7124 next;
7125 }
7126 }
7127 elsif($OSgroup eq "macos")
7128 { # seach in frameworks
7129 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7130 {
7131 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7132 {# frameworks
7133 my ($HFramework, $HName) = ($1, $2);
7134 $Dep = $HFramework;
7135 }
7136 else
7137 {# mismatch
7138 next;
7139 }
7140 }
7141 }
7142 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7143 { # Linux, FreeBSD
7144 next;
7145 }
7146 }
7147 if(not $Dep)
7148 { # nothing to include
7149 next;
7150 }
7151 if(is_default_include_dir($Dep))
7152 { # included by the compiler
7153 next;
7154 }
7155 if(get_depth($Dep)==1)
7156 { # too short
7157 next;
7158 }
7159 if(isLibcDir($Dep))
7160 { # do NOT include /usr/include/{sys,bits}
7161 next;
7162 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007163 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007164 }
7165 }
7166 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7167 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7168}
7169
7170sub sortIncPaths($$)
7171{
7172 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007173 if(not $ArrRef or $#{$ArrRef}<0) {
7174 return $ArrRef;
7175 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007176 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7177 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007178 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007179 return $ArrRef;
7180}
7181
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007182sub sortDeps($$$)
7183{
7184 if($Header_Dependency{$_[2]}{$_[0]}
7185 and not $Header_Dependency{$_[2]}{$_[1]}) {
7186 return 1;
7187 }
7188 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7189 and $Header_Dependency{$_[2]}{$_[1]}) {
7190 return -1;
7191 }
7192 return 0;
7193}
7194
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007195sub join_P($$)
7196{
7197 my $S = "/";
7198 if($OSgroup eq "windows") {
7199 $S = "\\";
7200 }
7201 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007202}
7203
7204sub get_namespace_additions($)
7205{
7206 my $NameSpaces = $_[0];
7207 my ($Additions, $AddNameSpaceId) = ("", 1);
7208 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7209 {
7210 next if($SkipNameSpaces{$Version}{$NS});
7211 next if(not $NS or $NameSpaces->{$NS}==-1);
7212 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7213 next if($NS=~/\A__/i);
7214 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007215 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007216 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7217 my @NS_Parts = split(/::/, $NS);
7218 next if($#NS_Parts==-1);
7219 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7220 foreach my $NS_Part (@NS_Parts)
7221 {
7222 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7223 $TypeDecl_Suffix .= "}";
7224 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007225 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007226 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7227 $Additions.=" $TypeDecl\n $FuncDecl\n";
7228 $AddNameSpaceId+=1;
7229 }
7230 return $Additions;
7231}
7232
7233sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007234{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007235 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007236 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007237 if($Fmt eq "windows")
7238 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007239 $Path=~s/\//\\/g;
7240 $Path=lc($Path);
7241 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007242 else
7243 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007244 $Path=~s/\\/\//g;
7245 }
7246 return $Path;
7247}
7248
7249sub inc_opt($$)
7250{
7251 my ($Path, $Style) = @_;
7252 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007253 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007254 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007255 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007256 return "-I\"".path_format($Path, "unix")."\"";
7257 }
7258 elsif($OSgroup eq "macos"
7259 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007260 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007261 return "-F".esc(get_dirname($Path));
7262 }
7263 else {
7264 return "-I".esc($Path);
7265 }
7266 }
7267 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007268 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007269 }
7270 return "";
7271}
7272
7273sub platformSpecs($)
7274{
7275 my $LibVersion = $_[0];
7276 my $Arch = getArch($LibVersion);
7277 if($OStarget eq "symbian")
7278 { # options for GCCE compiler
7279 my %Symbian_Opts = map {$_=>1} (
7280 "-D__GCCE__",
7281 "-DUNICODE",
7282 "-fexceptions",
7283 "-D__SYMBIAN32__",
7284 "-D__MARM_INTERWORK__",
7285 "-D_UNICODE",
7286 "-D__S60_50__",
7287 "-D__S60_3X__",
7288 "-D__SERIES60_3X__",
7289 "-D__EPOC32__",
7290 "-D__MARM__",
7291 "-D__EABI__",
7292 "-D__MARM_ARMV5__",
7293 "-D__SUPPORT_CPP_EXCEPTIONS__",
7294 "-march=armv5t",
7295 "-mapcs",
7296 "-mthumb-interwork",
7297 "-DEKA2",
7298 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
7299 );
7300 return join(" ", keys(%Symbian_Opts));
7301 }
7302 elsif($OSgroup eq "windows"
7303 and get_dumpmachine($GCC_PATH)=~/mingw/i)
7304 { # add options to MinGW compiler
7305 # to simulate the MSVC compiler
7306 my %MinGW_Opts = map {$_=>1} (
7307 "-D_WIN32",
7308 "-D_STDCALL_SUPPORTED",
7309 "-D__int64=\"long long\"",
7310 "-D__int32=int",
7311 "-D__int16=short",
7312 "-D__int8=char",
7313 "-D__possibly_notnullterminated=\" \"",
7314 "-D__nullterminated=\" \"",
7315 "-D__nullnullterminated=\" \"",
7316 "-D__w64=\" \"",
7317 "-D__ptr32=\" \"",
7318 "-D__ptr64=\" \"",
7319 "-D__forceinline=inline",
7320 "-D__inline=inline",
7321 "-D__uuidof(x)=IID()",
7322 "-D__try=",
7323 "-D__except(x)=",
7324 "-D__declspec(x)=__attribute__((x))",
7325 "-D__pragma(x)=",
7326 "-D_inline=inline",
7327 "-D__forceinline=__inline",
7328 "-D__stdcall=__attribute__((__stdcall__))",
7329 "-D__cdecl=__attribute__((__cdecl__))",
7330 "-D__fastcall=__attribute__((__fastcall__))",
7331 "-D__thiscall=__attribute__((__thiscall__))",
7332 "-D_stdcall=__attribute__((__stdcall__))",
7333 "-D_cdecl=__attribute__((__cdecl__))",
7334 "-D_fastcall=__attribute__((__fastcall__))",
7335 "-D_thiscall=__attribute__((__thiscall__))",
7336 "-DSHSTDAPI_(x)=x",
7337 "-D_MSC_EXTENSIONS",
7338 "-DSECURITY_WIN32",
7339 "-D_MSC_VER=1500",
7340 "-D_USE_DECLSPECS_FOR_SAL",
7341 "-D__noop=\" \"",
7342 "-DDECLSPEC_DEPRECATED=\" \"",
7343 "-D__builtin_alignof(x)=__alignof__(x)",
7344 "-DSORTPP_PASS");
7345 if($Arch eq "x86") {
7346 $MinGW_Opts{"-D_M_IX86=300"}=1;
7347 }
7348 elsif($Arch eq "x86_64") {
7349 $MinGW_Opts{"-D_M_AMD64=300"}=1;
7350 }
7351 elsif($Arch eq "ia64") {
7352 $MinGW_Opts{"-D_M_IA64=300"}=1;
7353 }
7354 return join(" ", keys(%MinGW_Opts));
7355 }
7356 return "";
7357}
7358
7359my %C_Structure = map {$_=>1} (
7360# FIXME: Can't separate union and struct data types before dumping,
7361# so it sometimes cause compilation errors for unknown reason
7362# when trying to declare TYPE* tmp_add_class_N
7363# This is a list of such structures + list of other C structures
7364 "sigval",
7365 "sigevent",
7366 "sigaction",
7367 "sigvec",
7368 "sigstack",
7369 "timeval",
7370 "timezone",
7371 "rusage",
7372 "rlimit",
7373 "wait",
7374 "flock",
7375 "stat",
7376 "_stat",
7377 "stat32",
7378 "_stat32",
7379 "stat64",
7380 "_stat64",
7381 "_stati64",
7382 "if_nameindex",
7383 "usb_device",
7384 "sigaltstack",
7385 "sysinfo",
7386 "timeLocale",
7387 "tcp_debug",
7388 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007389 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007390 "timespec",
7391 "random_data",
7392 "drand48_data",
7393 "_IO_marker",
7394 "_IO_FILE",
7395 "lconv",
7396 "sched_param",
7397 "tm",
7398 "itimerspec",
7399 "_pthread_cleanup_buffer",
7400 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007401 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007402 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007403 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007404 "sigcontext",
7405 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007406 # Mac
7407 "_timex",
7408 "_class_t",
7409 "_category_t",
7410 "_class_ro_t",
7411 "_protocol_t",
7412 "_message_ref_t",
7413 "_super_message_ref_t",
7414 "_ivar_t",
7415 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007416);
7417
7418sub getCompileCmd($$$)
7419{
7420 my ($Path, $Opt, $Inc) = @_;
7421 my $GccCall = $GCC_PATH;
7422 if($Opt) {
7423 $GccCall .= " ".$Opt;
7424 }
7425 $GccCall .= " -x ";
7426 if($OSgroup eq "macos") {
7427 $GccCall .= "objective-";
7428 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007429 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007430 { # compile as "C++" header
7431 # to obtain complete dump using GCC 4.0
7432 $GccCall .= "c++-header";
7433 }
7434 else
7435 { # compile as "C++" source
7436 # GCC 3.3 cannot compile headers
7437 $GccCall .= "c++";
7438 }
7439 if(my $Opts = platformSpecs($Version))
7440 {# platform-specific options
7441 $GccCall .= " ".$Opts;
7442 }
7443 # allow extra qualifications
7444 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007445 $GccCall .= " -fpermissive";
7446 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007447 if($NoStdInc)
7448 {
7449 $GccCall .= " -nostdinc";
7450 $GccCall .= " -nostdinc++";
7451 }
7452 if($CompilerOptions{$Version})
7453 { # user-defined options
7454 $GccCall .= " ".$CompilerOptions{$Version};
7455 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007456 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007457 if($Inc)
7458 { # include paths
7459 $GccCall .= " ".$Inc;
7460 }
7461 return $GccCall;
7462}
7463
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007464sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007465{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007466 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007467 my %HeaderElems = (
7468 # Types
7469 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007470 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007471 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
7472 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007473 "time.h" => ["time_t"],
7474 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007475 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
7476 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007477 "stdbool.h" => ["_Bool"],
7478 "rpc/xdr.h" => ["bool_t"],
7479 "in_systm.h" => ["n_long", "n_short"],
7480 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04007481 "arpa/inet.h" => ["fw_src", "ip_src"],
7482 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007483 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007484 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007485 );
7486 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007487 foreach (keys(%HeaderElems))
7488 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007489 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007490 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007491 }
7492 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007493 my %Types = ();
7494 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
7495 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007496 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007497 }
7498 if(keys(%Types))
7499 {
7500 my %AddHeaders = ();
7501 foreach my $Type (keys(%Types))
7502 {
7503 if(my $Header = $AutoPreamble{$Type})
7504 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007505 if(my $Path = identifyHeader($Header, $LibVersion))
7506 {
7507 if(skipHeader($Path, $LibVersion)) {
7508 next;
7509 }
7510 $Path = path_format($Path, $OSgroup);
7511 $AddHeaders{$Path}{"Type"} = $Type;
7512 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007513 }
7514 }
7515 }
7516 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007517 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007518 }
7519 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007520 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007521}
7522
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007523sub checkCTags($)
7524{
7525 my $Path = $_[0];
7526 if(not $Path) {
7527 return;
7528 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007529 my $CTags = undef;
7530
7531 if($OSgroup eq "bsd")
7532 { # use ectags on BSD
7533 $CTags = get_CmdPath("ectags");
7534 if(not $CTags) {
7535 printMsg("WARNING", "can't find \'ectags\' program");
7536 }
7537 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007538 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007539 $CTags = get_CmdPath("ctags");
7540 }
7541 if(not $CTags)
7542 {
7543 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007544 return;
7545 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04007546
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007547 if($OSgroup ne "linux")
7548 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04007549 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
7550 if($Info!~/exuberant/i)
7551 {
7552 printMsg("WARNING", "incompatible version of \'ctags\' program");
7553 return;
7554 }
7555 }
7556
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007557 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04007558 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007559 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007560 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007561 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007562 open(CTAGS, "<", $Out);
7563 while(my $Line = <CTAGS>)
7564 {
7565 chomp($Line);
7566 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007567 if(defined $Intrinsic_Keywords{$Name})
7568 { # noise
7569 next;
7570 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007571 if($Type eq "n")
7572 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007573 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007574 next;
7575 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007576 if(index($Scpe, "struct:")==0) {
7577 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007578 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007579 if(index($Scpe, "namespace:")==0)
7580 {
7581 if($Scpe=~s/\Anamespace://) {
7582 $Name = $Scpe."::".$Name;
7583 }
7584 }
7585 $TUnit_NameSpaces{$Version}{$Name} = 1;
7586 }
7587 elsif($Type eq "p")
7588 {
7589 if(not $Scpe or index($Scpe, "namespace:")==0) {
7590 $TUnit_Funcs{$Version}{$Name} = 1;
7591 }
7592 }
7593 elsif($Type eq "x")
7594 {
7595 if(not $Scpe or index($Scpe, "namespace:")==0) {
7596 $TUnit_Vars{$Version}{$Name} = 1;
7597 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007598 }
7599 }
7600 close(CTAGS);
7601}
7602
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007603sub getDump()
7604{
7605 if(not $GCC_PATH) {
7606 exitStatus("Error", "internal error - GCC path is not set");
7607 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007608 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007609 my $MHeaderPath = $TmpHeaderPath;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007610 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007611 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
7612 {
7613 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007614 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007615 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007616 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007617 foreach my $HPath (@{$Include_Preamble{$Version}}) {
7618 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007619 }
7620 my @Headers = keys(%{$Registered_Headers{$Version}});
7621 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007622 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007623 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007624 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
7625 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
7626 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007627 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007628 close(TMP_HEADER);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007629 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007630
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007631 if($ExtraInfo)
7632 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007633 if($IncludeString) {
7634 writeFile($ExtraInfo."/include-string", $IncludeString);
7635 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04007636 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
7637 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007638
7639 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
7640 {
7641 my $REDIR = "";
7642 foreach my $P1 (sort @Redirects) {
7643 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
7644 }
7645 writeFile($ExtraInfo."/include-redirect", $REDIR);
7646 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007647 }
7648
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007649 if(not keys(%{$TargetHeaders{$Version}}))
7650 { # Target headers
7651 addTargetHeaders($Version);
7652 }
7653
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007654 # clean memory
7655 %RecursiveIncludes = ();
7656 %Header_Include_Prefix = ();
7657 %Header_Includes = ();
7658
7659 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007660 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007661 delete($Cache{"detect_header_includes"});
7662 delete($Cache{"selectSystemHeader"});
7663
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007664 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007665 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
7666 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007667
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007668 if($ExtraInfo)
7669 { # extra information for other tools
7670 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
7671 }
7672
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007673 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007674 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007675 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007676
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007677 if($COMMON_LANGUAGE{$Version} eq "C++") {
7678 checkCTags($Pre);
7679 }
7680
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007681 my $MContent = "";
7682 my $PreprocessCmd = getCompileCmd($TmpHeaderPath, "-E", $IncludeString);
7683 if($OStarget eq "windows"
7684 and get_dumpmachine($GCC_PATH)=~/mingw/i
7685 and $MinGWMode{$Version}!=-1)
7686 { # modify headers to compile by MinGW
7687 if(not $MContent)
7688 { # preprocessing
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007689 $MContent = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007690 }
7691 if($MContent=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
7692 { # __asm { ... }
7693 $MinGWMode{$Version}=1;
7694 }
7695 if($MContent=~s/\s+(\/ \/.*?)\n/\n/g)
7696 { # comments after preprocessing
7697 $MinGWMode{$Version}=1;
7698 }
7699 if($MContent=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
7700 { # 0xffui8
7701 $MinGWMode{$Version}=1;
7702 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007703 if($MinGWMode{$Version})
7704 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007705 printMsg("INFO", "Using MinGW compatibility mode");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04007706 $MHeaderPath = $TMP_DIR."/dump$Version.i";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007707 }
7708 }
7709 if(($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007710 and $CppMode{$Version}!=-1 and not $CppCompat)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007711 { # rename C++ keywords in C code
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007712 # disable this code by -cpp-compatible option
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007713 if(not $MContent)
7714 { # preprocessing
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007715 $MContent = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007716 }
7717 my $RegExp_C = join("|", keys(%CppKeywords_C));
7718 my $RegExp_F = join("|", keys(%CppKeywords_F));
7719 my $RegExp_O = join("|", keys(%CppKeywords_O));
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04007720
7721 my $Detected = undef;
7722
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007723 while($MContent=~s/(\A|\n[^\#\/\n][^\n]*?|\n)(\*\s*|\s+|\@|\,|\()($RegExp_C|$RegExp_F)(\s*(\,|\)|\;|\-\>|\.|\:\s*\d))/$1$2c99_$3$4/g)
7724 { # MATCH:
7725 # int foo(int new, int class, int (*new)(int));
7726 # unsigned private: 8;
7727 # DO NOT MATCH:
7728 # #pragma GCC visibility push(default)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007729 $CppMode{$Version} = 1;
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04007730 $Detected = "$1$2$3$4" if(not defined $Detected);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007731 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007732 if($MContent=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007733 { # MATCH:
7734 # int delete(...);
7735 # int explicit(...);
7736 # DO NOT MATCH:
7737 # void operator delete(...)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007738 $CppMode{$Version} = 1;
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04007739 $Detected = "$1$2$3" if(not defined $Detected);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007740 }
7741 if($MContent=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
7742 { # MATCH:
7743 # int bool;
7744 # DO NOT MATCH:
7745 # bool X;
7746 # return *this;
7747 # throw;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007748 $CppMode{$Version} = 1;
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04007749 $Detected = "$1$2$3" if(not defined $Detected);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007750 }
7751 if($MContent=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
7752 { # MATCH:
7753 # int operator(...);
7754 # DO NOT MATCH:
7755 # int operator()(...);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007756 $CppMode{$Version} = 1;
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04007757 $Detected = "$1$2$3" if(not defined $Detected);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007758 }
7759 if($MContent=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
7760 { # MATCH:
7761 # int foo(int operator);
7762 # int foo(int operator, int other);
7763 # DO NOT MATCH:
7764 # int operator,(...);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007765 $CppMode{$Version} = 1;
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04007766 $Detected = "$1$2$3" if(not defined $Detected);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007767 }
7768 if($MContent=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
7769 { # MATCH:
7770 # int foo(gboolean *bool);
7771 # DO NOT MATCH:
7772 # void setTabEnabled(int index, bool);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007773 $CppMode{$Version} = 1;
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04007774 $Detected = "$1$2$3" if(not defined $Detected);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007775 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007776 if($MContent=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007777 { # MATCH:
7778 # int foo(int* this);
7779 # int bar(int this);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007780 # int baz(int throw);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007781 # DO NOT MATCH:
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007782 # foo(X, this);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007783 $CppMode{$Version} = 1;
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04007784 $Detected = "$1$2$3$4" if(not defined $Detected);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007785 }
7786
7787 if($CppMode{$Version} == 1)
7788 {
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04007789 if($Debug)
7790 {
7791 $Detected=~s/\A\s+//g;
7792 printMsg("INFO", "Detected code: \"$Detected\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007793 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007794 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007795
7796 # remove typedef enum NAME NAME;
7797 my @FwdTypedefs = $MContent=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
7798 my $N = 0;
7799 while($N<=$#FwdTypedefs-1)
7800 {
7801 my $S = $FwdTypedefs[$N];
7802 if($S eq $FwdTypedefs[$N+1])
7803 {
7804 $MContent=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007805 $CppMode{$Version}=1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007806 }
7807 $N+=2;
7808 }
7809
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007810 if($CppMode{$Version}==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007811 { # try to change C++ "keyword" to "c99_keyword"
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007812 printMsg("INFO", "Using C++ compatibility mode");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04007813 $MHeaderPath = $TMP_DIR."/dump$Version.i";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007814 }
7815 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007816 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007817 or $MinGWMode{$Version}==1)
7818 { # compile the corrected preprocessor output
7819 writeFile($MHeaderPath, $MContent);
7820 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007821
7822 # clean memory
7823 undef $MContent;
7824
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007825 if($COMMON_LANGUAGE{$Version} eq "C++")
7826 { # add classes and namespaces to the dump
7827 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007828 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007829 or $MinGWMode{$Version}==1) {
7830 $CHdump .= " -fpreprocessed";
7831 }
7832 my $ClassHierarchyCmd = getCompileCmd($MHeaderPath, $CHdump, $IncludeString);
7833 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007834 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007835 chdir($ORIG_DIR);
7836 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
7837 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007838 my $Content = readFile($ClassDump);
7839 foreach my $ClassInfo (split(/\n\n/, $Content))
7840 {
7841 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
7842 {
7843 my $CName = $1;
7844 next if($CName=~/\A(__|_objc_|_opaque_)/);
7845 $TUnit_NameSpaces{$Version}{$CName} = -1;
7846 if($CName=~/\A[\w:]+\Z/)
7847 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007848 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007849 }
7850 if($CName=~/(\w[\w:]*)::/)
7851 { # namespaces
7852 my $NS = $1;
7853 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
7854 $TUnit_NameSpaces{$Version}{$NS} = 1;
7855 }
7856 }
7857 }
7858 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
7859 { # read v-tables (advanced approach)
7860 my ($CName, $VTable) = ($1, $2);
7861 $ClassVTable_Content{$Version}{$CName} = $VTable;
7862 }
7863 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007864 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
7865 { # add user-defined namespaces
7866 $TUnit_NameSpaces{$Version}{$NS} = 1;
7867 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007868 if($Debug)
7869 { # debug mode
7870 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007871 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007872 }
7873 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007874 }
7875
7876 # add namespaces and classes
7877 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
7878 { # GCC on all supported platforms does not include namespaces to the dump by default
7879 appendFile($MHeaderPath, "\n // add namespaces\n".$NS_Add);
7880 }
7881 # some GCC versions don't include class methods to the TU dump by default
7882 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007883 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007884 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
7885 {
7886 next if($C_Structure{$CName});
7887 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007888 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007889 if(not $Force and $GCC_44
7890 and $OSgroup eq "linux")
7891 { # optimization for linux with GCC >= 4.4
7892 # disable this code by -force option
7893 if(index($CName, "::")!=-1)
7894 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007895 next;
7896 }
7897 }
7898 else
7899 {
7900 if($CName=~/\A(.+)::[^:]+\Z/
7901 and $TUnit_Classes{$Version}{$1})
7902 { # classes inside other classes
7903 next;
7904 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007905 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007906 if(defined $TUnit_Funcs{$Version}{$CName})
7907 { # the same name for a function and type
7908 next;
7909 }
7910 if(defined $TUnit_Vars{$Version}{$CName})
7911 { # the same name for a variable and type
7912 next;
7913 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007914 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
7915 }
7916 if($AddClass) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007917 appendFile($MHeaderPath, "\n // add classes\n".$AddClass);
7918 }
7919 }
7920 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
7921 # create TU dump
7922 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007923 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007924 or $MinGWMode{$Version}==1) {
7925 $TUdump .= " -fpreprocessed";
7926 }
7927 my $SyntaxTreeCmd = getCompileCmd($MHeaderPath, $TUdump, $IncludeString);
7928 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
7929 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007930 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007931 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007932 if($?)
7933 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007934 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007935 { # try to recompile
7936 # FIXME: handle other errors and try to recompile
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007937 if($CppMode{$Version}==1
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007938 and index($Errors, "c99_")!=-1)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007939 { # disable c99 mode and try again
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007940 $CppMode{$Version}=-1;
7941 printMsg("INFO", "Disabling C++ compatibility mode");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007942 resetLogging($Version);
7943 $TMP_DIR = tempdir(CLEANUP=>1);
7944 return getDump();
7945 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007946 elsif($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007947 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007948 { # add auto preamble headers and try again
7949 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007950 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007951 foreach my $Num (0 .. $#Headers)
7952 {
7953 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007954 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
7955 {
7956 push_U($Include_Preamble{$Version}, $Path);
7957 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007958 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007959 }
7960 resetLogging($Version);
7961 $TMP_DIR = tempdir(CLEANUP=>1);
7962 return getDump();
7963 }
7964 elsif($Cpp0xMode{$Version}!=-1
7965 and ($Errors=~/\Q-std=c++0x\E/
7966 or $Errors=~/is not a class or namespace/))
7967 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007968 if(check_gcc($GCC_PATH, "4.6"))
7969 {
7970 $Cpp0xMode{$Version}=-1;
7971 printMsg("INFO", "Enabling c++0x mode");
7972 resetLogging($Version);
7973 $TMP_DIR = tempdir(CLEANUP=>1);
7974 $CompilerOptions{$Version} .= " -std=c++0x";
7975 return getDump();
7976 }
7977 else {
7978 printMsg("WARNING", "Probably c++0x construction detected");
7979 }
7980
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007981 }
7982 elsif($MinGWMode{$Version}==1)
7983 { # disable MinGW mode and try again
7984 $MinGWMode{$Version}=-1;
7985 resetLogging($Version);
7986 $TMP_DIR = tempdir(CLEANUP=>1);
7987 return getDump();
7988 }
7989 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007990 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007991 else {
7992 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007993 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007994 printMsg("ERROR", "some errors occurred when compiling headers");
7995 printErrorLog($Version);
7996 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007997 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007998 }
7999 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008000 unlink($TmpHeaderPath);
8001 unlink($MHeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008002
8003 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8004 return $TUs[0];
8005 }
8006 else
8007 {
8008 my $Msg = "can't compile header(s)";
8009 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8010 $Msg .= "\nDid you install G++?";
8011 }
8012 exitStatus("Cannot_Compile", $Msg);
8013 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008014}
8015
8016sub cmd_file($)
8017{
8018 my $Path = $_[0];
8019 return "" if(not $Path or not -e $Path);
8020 if(my $CmdPath = get_CmdPath("file")) {
8021 return `$CmdPath -b \"$Path\"`;
8022 }
8023 return "";
8024}
8025
8026sub getIncString($$)
8027{
8028 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008029 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008030 my $String = "";
8031 foreach (@{$ArrRef}) {
8032 $String .= " ".inc_opt($_, $Style);
8033 }
8034 return $String;
8035}
8036
8037sub getIncPaths(@)
8038{
8039 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008040 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008041 if($INC_PATH_AUTODETECT{$Version})
8042 { # auto-detecting dependencies
8043 my %Includes = ();
8044 foreach my $HPath (@HeaderPaths)
8045 {
8046 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8047 {
8048 if($Skip_Include_Paths{$Version}{$Dir}) {
8049 next;
8050 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008051 if($SystemRoot)
8052 {
8053 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8054 next;
8055 }
8056 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008057 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008058 }
8059 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008060 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008061 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008062 }
8063 }
8064 else
8065 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008066 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008067 }
8068 return \@IncPaths;
8069}
8070
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008071sub push_U($@)
8072{ # push unique
8073 if(my $Array = shift @_)
8074 {
8075 if(@_)
8076 {
8077 my %Exist = map {$_=>1} @{$Array};
8078 foreach my $Elem (@_)
8079 {
8080 if(not defined $Exist{$Elem})
8081 {
8082 push(@{$Array}, $Elem);
8083 $Exist{$Elem} = 1;
8084 }
8085 }
8086 }
8087 }
8088}
8089
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008090sub callPreprocessor($$$)
8091{
8092 my ($Path, $Inc, $LibVersion) = @_;
8093 return "" if(not $Path or not -f $Path);
8094 my $IncludeString=$Inc;
8095 if(not $Inc) {
8096 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8097 }
8098 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008099 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008100 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008101 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008102}
8103
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008104sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008105{ # native "find" is much faster than File::Find (~6x)
8106 # also the File::Find doesn't support --maxdepth N option
8107 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008108 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008109 return () if(not $Path or not -e $Path);
8110 if($OSgroup eq "windows")
8111 {
8112 my $DirCmd = get_CmdPath("dir");
8113 if(not $DirCmd) {
8114 exitStatus("Not_Found", "can't find \"dir\" command");
8115 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008116 $Path = get_abs_path($Path);
8117 $Path = path_format($Path, $OSgroup);
8118 my $Cmd = $DirCmd." \"$Path\" /B /O";
8119 if($MaxDepth!=1) {
8120 $Cmd .= " /S";
8121 }
8122 if($Type eq "d") {
8123 $Cmd .= " /AD";
8124 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008125 elsif($Type eq "f") {
8126 $Cmd .= " /A-D";
8127 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008128 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008129 if($Name)
8130 { # FIXME: how to search file names in MS shell?
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008131 if(not $UseRegex) {
8132 $Name=~s/\*/.*/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008133 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008134 @Files = grep { /\A$Name\Z/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008135 }
8136 my @AbsPaths = ();
8137 foreach my $File (@Files)
8138 {
8139 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008140 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008141 }
8142 if($Type eq "f" and not -f $File)
8143 { # skip dirs
8144 next;
8145 }
8146 push(@AbsPaths, path_format($File, $OSgroup));
8147 }
8148 if($Type eq "d") {
8149 push(@AbsPaths, $Path);
8150 }
8151 return @AbsPaths;
8152 }
8153 else
8154 {
8155 my $FindCmd = get_CmdPath("find");
8156 if(not $FindCmd) {
8157 exitStatus("Not_Found", "can't find a \"find\" command");
8158 }
8159 $Path = get_abs_path($Path);
8160 if(-d $Path and -l $Path
8161 and $Path!~/\/\Z/)
8162 { # for directories that are symlinks
8163 $Path.="/";
8164 }
8165 my $Cmd = $FindCmd." \"$Path\"";
8166 if($MaxDepth) {
8167 $Cmd .= " -maxdepth $MaxDepth";
8168 }
8169 if($Type) {
8170 $Cmd .= " -type $Type";
8171 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008172 if($Name and not $UseRegex)
8173 { # wildcards
8174 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008175 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008176 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
8177 if($?) {
8178 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8179 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008180 my @Files = split(/\n/, $Res);
8181 if($Name and $UseRegex)
8182 { # regex
8183 @Files = grep { /\A$Name\Z/ } @Files;
8184 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008185 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008186 }
8187}
8188
8189sub unpackDump($)
8190{
8191 my $Path = $_[0];
8192 return "" if(not $Path or not -e $Path);
8193 $Path = get_abs_path($Path);
8194 $Path = path_format($Path, $OSgroup);
8195 my ($Dir, $FileName) = separate_path($Path);
8196 my $UnpackDir = $TMP_DIR."/unpack";
8197 rmtree($UnpackDir);
8198 mkpath($UnpackDir);
8199 if($FileName=~s/\Q.zip\E\Z//g)
8200 { # *.zip
8201 my $UnzipCmd = get_CmdPath("unzip");
8202 if(not $UnzipCmd) {
8203 exitStatus("Not_Found", "can't find \"unzip\" command");
8204 }
8205 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008206 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008207 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008208 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008209 }
8210 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008211 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008212 if(not @Contents) {
8213 exitStatus("Error", "can't extract \'$Path\'");
8214 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008215 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008216 }
8217 elsif($FileName=~s/\Q.tar.gz\E\Z//g)
8218 { # *.tar.gz
8219 if($OSgroup eq "windows")
8220 { # -xvzf option is not implemented in tar.exe (2003)
8221 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8222 my $TarCmd = get_CmdPath("tar");
8223 if(not $TarCmd) {
8224 exitStatus("Not_Found", "can't find \"tar\" command");
8225 }
8226 my $GzipCmd = get_CmdPath("gzip");
8227 if(not $GzipCmd) {
8228 exitStatus("Not_Found", "can't find \"gzip\" command");
8229 }
8230 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008231 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008232 if($?) {
8233 exitStatus("Error", "can't extract \'$Path\'");
8234 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008235 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008236 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008237 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008238 }
8239 chdir($ORIG_DIR);
8240 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008241 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008242 if(not @Contents) {
8243 exitStatus("Error", "can't extract \'$Path\'");
8244 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008245 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008246 }
8247 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008248 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008249 my $TarCmd = get_CmdPath("tar");
8250 if(not $TarCmd) {
8251 exitStatus("Not_Found", "can't find \"tar\" command");
8252 }
8253 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008254 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008255 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008256 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008257 }
8258 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008259 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008260 if(not @Contents) {
8261 exitStatus("Error", "can't extract \'$Path\'");
8262 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008263 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008264 }
8265 }
8266}
8267
8268sub createArchive($$)
8269{
8270 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008271 if(not $To) {
8272 $To = ".";
8273 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008274 if(not $Path or not -e $Path
8275 or not -d $To) {
8276 return "";
8277 }
8278 my ($From, $Name) = separate_path($Path);
8279 if($OSgroup eq "windows")
8280 { # *.zip
8281 my $ZipCmd = get_CmdPath("zip");
8282 if(not $ZipCmd) {
8283 exitStatus("Not_Found", "can't find \"zip\"");
8284 }
8285 my $Pkg = $To."/".$Name.".zip";
8286 unlink($Pkg);
8287 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008288 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008289 if($?)
8290 { # cannot allocate memory (or other problems with "zip")
8291 unlink($Path);
8292 exitStatus("Error", "can't pack the ABI dump: ".$!);
8293 }
8294 chdir($ORIG_DIR);
8295 unlink($Path);
8296 return $Pkg;
8297 }
8298 else
8299 { # *.tar.gz
8300 my $TarCmd = get_CmdPath("tar");
8301 if(not $TarCmd) {
8302 exitStatus("Not_Found", "can't find \"tar\"");
8303 }
8304 my $GzipCmd = get_CmdPath("gzip");
8305 if(not $GzipCmd) {
8306 exitStatus("Not_Found", "can't find \"gzip\"");
8307 }
8308 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
8309 unlink($Pkg);
8310 chdir($From);
8311 system($TarCmd, "-czf", $Pkg, $Name);
8312 if($?)
8313 { # cannot allocate memory (or other problems with "tar")
8314 unlink($Path);
8315 exitStatus("Error", "can't pack the ABI dump: ".$!);
8316 }
8317 chdir($ORIG_DIR);
8318 unlink($Path);
8319 return $To."/".$Name.".tar.gz";
8320 }
8321}
8322
8323sub is_header_file($)
8324{
8325 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
8326 return $_[0];
8327 }
8328 return 0;
8329}
8330
8331sub is_not_header($)
8332{
8333 if($_[0]=~/\.\w+\Z/
8334 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
8335 return 1;
8336 }
8337 return 0;
8338}
8339
8340sub is_header($$$)
8341{
8342 my ($Header, $UserDefined, $LibVersion) = @_;
8343 return 0 if(-d $Header);
8344 if(-f $Header) {
8345 $Header = get_abs_path($Header);
8346 }
8347 else
8348 {
8349 if(is_abs($Header))
8350 { # incorrect absolute path
8351 return 0;
8352 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008353 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008354 $Header = $HPath;
8355 }
8356 else
8357 { # can't find header
8358 return 0;
8359 }
8360 }
8361 if($Header=~/\.\w+\Z/)
8362 { # have an extension
8363 return is_header_file($Header);
8364 }
8365 else
8366 {
8367 if($UserDefined==2)
8368 { # specified on the command line
8369 if(cmd_file($Header)!~/HTML|XML/i) {
8370 return $Header;
8371 }
8372 }
8373 elsif($UserDefined)
8374 { # specified in the XML-descriptor
8375 # header file without an extension
8376 return $Header;
8377 }
8378 else
8379 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008380 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008381 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008382 { # !~/HTML|XML|shared|dynamic/i
8383 return $Header;
8384 }
8385 }
8386 }
8387 return 0;
8388}
8389
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008390sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008391{
8392 my $LibVersion = $_[0];
8393 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
8394 {
8395 my $RegDir = get_dirname($RegHeader);
8396 $TargetHeaders{$LibVersion}{get_filename($RegHeader)}=1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008397
8398 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
8399 detect_recursive_includes($RegHeader, $LibVersion);
8400 }
8401
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008402 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
8403 {
8404 my $Dir = get_dirname($RecInc);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008405 if($Dir=~/\A\Q$RegDir\E([\/\\]|\Z)/
8406 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
8407 { # in the same directory or included by #include "..."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008408 $TargetHeaders{$LibVersion}{get_filename($RecInc)}=1;
8409 }
8410 }
8411 }
8412}
8413
8414sub readHeaders($)
8415{
8416 $Version = $_[0];
8417 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
8418 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008419 if($Debug)
8420 { # debug mode
8421 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008422 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008423 }
8424 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008425}
8426
8427sub prepareTypes($)
8428{
8429 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008430 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008431 { # support for old ABI dumps
8432 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008433 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008434 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008435 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
8436 if($TName=~/\A(\w+)::(\w+)/) {
8437 my ($P1, $P2) = ($1, $2);
8438 if($P1 eq $P2) {
8439 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008440 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008441 else {
8442 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
8443 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008444 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008445 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008446 }
8447 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008448 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008449 { # support for old ABI dumps
8450 # V < 2.5: array size == "number of elements"
8451 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008452 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008453 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008454 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008455 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008456 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008457 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008458 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008459 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008460 $Size *= $Base{"Size"};
8461 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008462 }
8463 else
8464 { # array[] is a pointer
8465 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008466 }
8467 }
8468 }
8469 }
8470 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008471 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008472 { # support for old ABI dumps
8473 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008474 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008475 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008476 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008477 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008478 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008479 my %Type = get_Type($TypeId, $LibVersion);
8480 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
8481 my %Type2 = get_Type($TypeId_2, $V2);
8482 if($Type{"Size"} ne $Type2{"Size"}) {
8483 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008484 }
8485 }
8486 }
8487 }
8488}
8489
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008490sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008491{
8492 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008493
8494 if(not keys(%{$SymbolInfo{$LibVersion}}))
8495 { # check if input is valid
8496 if(not $ExtendedCheck and not $CheckObjectsOnly)
8497 {
8498 if($CheckHeadersOnly) {
8499 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
8500 }
8501 else {
8502 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
8503 }
8504 }
8505 }
8506
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008507 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008508 if(not checkDump(1, "2.10")
8509 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008510 { # different formats
8511 $Remangle = 1;
8512 }
8513 if($CheckHeadersOnly)
8514 { # different languages
8515 if($UserLang)
8516 { # --lang=LANG for both versions
8517 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
8518 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
8519 {
8520 if($UserLang eq "C++")
8521 { # remangle symbols
8522 $Remangle = 1;
8523 }
8524 elsif($UserLang eq "C")
8525 { # remove mangling
8526 $Remangle = -1;
8527 }
8528 }
8529 }
8530 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008531
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008532 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008533 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008534 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04008535 { # support for old ABI dumps
8536 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
8537 {
8538 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
8539 {
8540 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
8541 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008542 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04008543 if(defined $DVal and $DVal ne "")
8544 {
8545 if($TName eq "char") {
8546 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
8547 }
8548 elsif($TName eq "bool") {
8549 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
8550 }
8551 }
8552 }
8553 }
8554 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008555 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008556 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008557 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
8558 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008559 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008560 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
8561 # + support for old ABI dumps
8562 next;
8563 }
8564 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008565 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008566 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008567 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008568 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008569
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008570 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008571 if(not checkDump(1, "2.12")
8572 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008573 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008574 if($ShortName eq "operator>>")
8575 {
8576 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
8577 { # corrected mangling of operator>>
8578 $SRemangle = 1;
8579 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008580 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008581 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
8582 {
8583 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
8584 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
8585 { # corrected mangling of const global data
8586 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
8587 # and incorrectly mangled by old ACC versions
8588 $SRemangle = 1;
8589 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008590 }
8591 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008592 if(not $CheckHeadersOnly)
8593 { # support for old ABI dumps
8594 if(not checkDump(1, "2.17")
8595 or not checkDump(2, "2.17"))
8596 {
8597 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
8598 {
8599 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
8600 {
8601 if(link_symbol($ShortName, $LibVersion, "-Deps"))
8602 {
8603 $MnglName = $ShortName;
8604 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
8605 }
8606 }
8607 }
8608 }
8609 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008610 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008611 { # support for old ABI dumps: some symbols are not mangled in old dumps
8612 # mangle both sets of symbols (old and new)
8613 # NOTE: remangling all symbols by the same mangler
8614 if($MnglName=~/\A_ZN(V|)K/)
8615 { # mangling may be incorrect on old ABI dumps
8616 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008617 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008618 }
8619 if($MnglName=~/\A_ZN(K|)V/)
8620 { # mangling may be incorrect on old ABI dumps
8621 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008622 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008623 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008624 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
8625 or (not $ClassID and $CheckHeadersOnly)
8626 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
8627 { # support for old ABI dumps, GCC >= 4.0
8628 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008629 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008630 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008631 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008632 $MangledNames{$LibVersion}{$MnglName} = 1;
8633 }
8634 }
8635 }
8636 elsif($Remangle==-1)
8637 { # remove mangling
8638 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008639 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008640 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008641 if(not $MnglName) {
8642 next;
8643 }
8644 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
8645 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008646 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
8647
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008648 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008649 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008650 { # support for old dumps
8651 # add "Volatile" attribute
8652 if($MnglName=~/_Z(K|)V/) {
8653 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
8654 }
8655 }
8656 # symbol and its symlink have same signatures
8657 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008658 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008659 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008660
8661 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008662 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008663 }
8664 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
8665 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
8666 }
8667 if($ExtendedCheck)
8668 { # --ext option
8669 addExtension($LibVersion);
8670 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008671
8672 # clean memory
8673 delete($SymbolInfo{$LibVersion});
8674
8675 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008676 { # detect allocable classes with public exported constructors
8677 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008678 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008679 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008680 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008681 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008682 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
8683 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008684 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008685 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008686 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008687 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008688 $AllocableClass{$LibVersion}{$ClassName} = 1;
8689 }
8690 }
8691 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008692 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008693 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008694 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008695 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008696 if($CheckHeadersOnly)
8697 {
8698 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
8699 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
8700 { # all symbols except non-virtual inline
8701 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
8702 }
8703 }
8704 else {
8705 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008706 }
8707 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008708 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008709 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008710 }
8711 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008712 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008713 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008714 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008715 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008716 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008717 if(defined $Base{"Type"}
8718 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008719 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008720 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008721 if($Name=~/<([^<>\s]+)>/)
8722 {
8723 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
8724 $ReturnedClass{$LibVersion}{$Tid} = 1;
8725 }
8726 }
8727 else {
8728 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
8729 }
8730 }
8731 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008732 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008733 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008734 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008735 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008736 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008737 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008738 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008739 if($Base{"Type"}=~/Struct|Class/)
8740 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008741 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008742 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
8743 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008744 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008745 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008746 }
8747 }
8748 }
8749 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008750
8751 # mapping {short name => symbols}
8752 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008753 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008754 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008755 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008756 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008757 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008758 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008759 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008760 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
8761 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008762 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008763 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008764 }
8765 }
8766 }
8767 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008768
8769 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008770 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008771 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008772 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008773 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008774 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
8775 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008776 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008777 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008778 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008779 $ClassNames{$LibVersion}{$TName} = 1;
8780 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008781 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008782 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
8783 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008784 }
8785 }
8786 }
8787 }
8788 }
8789}
8790
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008791sub register_TypeUsage($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008792{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008793 my ($TypeId, $LibVersion) = @_;
8794 if(not $TypeId) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008795 return 0;
8796 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008797 if($UsedType{$LibVersion}{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008798 { # already registered
8799 return 1;
8800 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008801 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008802 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008803 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008804 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|MethodPtr|FieldPtr|Enum)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008805 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008806 $UsedType{$LibVersion}{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008807 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008808 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008809 foreach my $BaseId (keys(%{$TInfo{"Base"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008810 { # register base classes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008811 register_TypeUsage($BaseId, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008812 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008813 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
8814 {
8815 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
8816 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008817 register_TypeUsage($TTid, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008818 }
8819 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008820 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008821 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008822 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008823 if(my $MTid = $TInfo{"Memb"}{$Memb_Pos}{"type"}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008824 register_TypeUsage($MTid, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008825 }
8826 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008827 if($TInfo{"Type"} eq "FuncPtr"
8828 or $TInfo{"Type"} eq "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008829 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008830 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008831 register_TypeUsage($RTid, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008832 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008833 foreach my $Memb_Pos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008834 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008835 if(my $MTid = $TInfo{"Param"}{$Memb_Pos}{"type"}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008836 register_TypeUsage($MTid, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008837 }
8838 }
8839 }
8840 return 1;
8841 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008842 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008843 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008844 $UsedType{$LibVersion}{$TypeId} = 1;
8845 register_TypeUsage($TInfo{"BaseType"}{"Tid"}, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008846 return 1;
8847 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008848 elsif($TInfo{"Type"} eq "Intrinsic")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008849 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008850 $UsedType{$LibVersion}{$TypeId} = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008851 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008852 }
8853 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008854 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008855}
8856
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008857sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04008858{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008859 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
8860
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04008861 if($Level eq "Dump")
8862 {
8863 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
8864 { # TODO: check if this symbol is from
8865 # base classes of other target symbols
8866 return 1;
8867 }
8868 }
8869
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008870 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
8871 { # stdc++ interfaces
8872 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04008873 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008874
8875 my $Target = 0;
8876 if(my $Header = $SInfo->{"Header"}) {
8877 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
8878 }
8879 if($CheckHeadersOnly)
8880 {
8881 if($Target)
8882 {
8883 if($Level eq "Dump")
8884 { # dumped
8885 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04008886 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008887 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04008888 return 1;
8889 }
8890 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008891 else {
8892 return 1;
8893 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04008894 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008895 elsif($Level eq "Source")
8896 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04008897 return 1;
8898 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008899 elsif($Level eq "Binary")
8900 { # checked
8901 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
8902 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
8903 return 1;
8904 }
8905 }
8906 }
8907 }
8908 else
8909 { # library is available
8910 if(link_symbol($Symbol, $LibVersion, "-Deps"))
8911 { # exported symbols
8912 return 1;
8913 }
8914 if($Level eq "Dump")
8915 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04008916 if($BinaryOnly)
8917 {
8918 if($SInfo->{"Data"})
8919 {
8920 if($Target) {
8921 return 1;
8922 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008923 }
8924 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04008925 else
8926 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008927 if($Target) {
8928 return 1;
8929 }
8930 }
8931 }
8932 elsif($Level eq "Source")
8933 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008934 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
8935 or isInLineInst($Symbol, $SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04008936 { # skip LOCAL symbols
8937 if($Target) {
8938 return 1;
8939 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008940 }
8941 }
8942 elsif($Level eq "Binary")
8943 { # checked
8944 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
8945 {
8946 if($Target) {
8947 return 1;
8948 }
8949 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04008950 }
8951 }
8952 return 0;
8953}
8954
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008955sub cleanDump($)
8956{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008957 my $LibVersion = $_[0];
8958 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
8959 {
8960 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
8961 if(not $MnglName) {
8962 delete($SymbolInfo{$LibVersion}{$InfoId});
8963 next;
8964 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008965 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008966 if(not $ShortName) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04008967 delete($SymbolInfo{$LibVersion}{$InfoId});
8968 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008969 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008970 if($MnglName eq $ShortName)
8971 { # remove duplicate data
8972 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008973 }
8974 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
8975 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
8976 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008977 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
8978 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
8979 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008980 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008981 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008982 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008983 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008984 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008985 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008986 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
8987 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
8988 }
8989 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008990 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
8991 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
8992 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008993 }
8994}
8995
8996sub selectType($$)
8997{
8998 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008999
9000 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9001 {
9002 if(defined $TypeInfo{$LibVersion}{$Dupl})
9003 {
9004 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9005 { # duplicate
9006 return 0;
9007 }
9008 }
9009 }
9010
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009011 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
9012 {
9013 if(not isBuiltIn($THeader))
9014 {
9015 if($TypeInfo{$LibVersion}{$Tid}{"Type"}=~/Class|Struct|Union|Enum|Typedef/)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009016 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009017 if(not isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"}))
9018 {
9019 if(is_target_header($THeader, $LibVersion))
9020 { # from target headers
9021 if(not selfTypedef($Tid, $LibVersion)) {
9022 return 1;
9023 }
9024 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009025 }
9026 }
9027 }
9028 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009029 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009030}
9031
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009032sub removeGarbage($)
9033{
9034 my $LibVersion = $_[0];
9035
9036
9037}
9038
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009039sub removeUnused($$)
9040{ # remove unused data types from the ABI dump
9041 my ($LibVersion, $Kind) = @_;
9042 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9043 {
9044 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9045 if(my $RTid = $FuncInfo{"Return"}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009046 register_TypeUsage($RTid, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009047 }
9048 if(my $FCid = $FuncInfo{"Class"})
9049 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009050 register_TypeUsage($FCid, $LibVersion);
9051 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009052 { # register "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009053 $UsedType{$LibVersion}{$ThisId} = 1;
9054 if(my %ThisType = get_Type($ThisId, $LibVersion)) {
9055 register_TypeUsage($ThisType{"BaseType"}{"Tid"}, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009056 }
9057 }
9058 }
9059 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9060 {
9061 if(my $PTid = $FuncInfo{"Param"}{$PPos}{"type"}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009062 register_TypeUsage($PTid, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009063 }
9064 }
9065 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9066 {
9067 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9068 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009069 register_TypeUsage($TTid, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009070 }
9071 }
9072 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009073 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
9074 {
9075 if($UsedType{$LibVersion}{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009076 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009077 next;
9078 }
9079
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009080 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009081 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009082 if(selectType($Tid, $LibVersion)) {
9083 register_TypeUsage($Tid, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009084 }
9085 }
9086 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009087 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
9088 { # remove unused types
9089 if($UsedType{$LibVersion}{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009090 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009091 next;
9092 }
9093 # remove type
9094 delete($TypeInfo{$LibVersion}{$Tid});
9095 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009096
9097 # clean memory
9098 %UsedType = ();
9099}
9100
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009101sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009102{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009103 my ($TypeId, $LibVersion) = @_;
9104 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009105 if($Type{"Type"} eq "Typedef")
9106 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009107 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009108 if($Base{"Type"}=~/Class|Struct/)
9109 {
9110 if($Type{"Name"} eq $Base{"Name"}) {
9111 return 1;
9112 }
9113 elsif($Type{"Name"}=~/::(\w+)\Z/)
9114 {
9115 if($Type{"Name"} eq $Base{"Name"}."::".$1)
9116 { # QPointer<QWidget>::QPointer
9117 return 1;
9118 }
9119 }
9120 }
9121 }
9122 return 0;
9123}
9124
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009125sub addExtension($)
9126{
9127 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009128 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009129 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009130 if(selectType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009131 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009132 my $Symbol = "external_func_".$TypeInfo{$LibVersion}{$Tid}{"Name"};
9133
9134 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
9135 "Header" => "extended.h",
9136 "ShortName" => $Symbol,
9137 "MnglName" => $Symbol,
9138 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
9139 );
9140
9141 $ExtendedSymbols{$Symbol}=1;
9142 $CheckedSymbols{"Binary"}{$Symbol}=1;
9143 $CheckedSymbols{"Source"}{$Symbol}=1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009144 }
9145 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009146 $ExtendedSymbols{"external_func_0"}=1;
9147 $CheckedSymbols{"Binary"}{"external_func_0"}=1;
9148 $CheckedSymbols{"Source"}{"external_func_0"}=1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009149}
9150
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009151sub findMethod($$$)
9152{
9153 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009154 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009155 {
9156 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
9157 return $VirtMethodInClass;
9158 }
9159 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
9160 return $VirtMethodInBaseClasses;
9161 }
9162 }
9163 return "";
9164}
9165
9166sub findMethod_Class($$$)
9167{
9168 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009169 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009170 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
9171 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
9172 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
9173 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
9174 { # search for interface with the same parameters suffix (overridden)
9175 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
9176 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04009177 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
9178 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009179 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
9180 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009181 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
9182 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
9183 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
9184 return $Candidate;
9185 }
9186 }
9187 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04009188 else
9189 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009190 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
9191 return $Candidate;
9192 }
9193 }
9194 }
9195 }
9196 return "";
9197}
9198
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009199sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009200{
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009201 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009202 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009203 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009204 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
9205 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009206 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009207 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009208 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009209 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
9210 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009211 { # pure virtual D2-destructors are marked as "virt" in the dump
9212 # virtual D2-destructors are NOT marked as "virt" in the dump
9213 # both destructors are not presented in the v-table
9214 next;
9215 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009216 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009217 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
9218 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009219 }
9220}
9221
9222sub registerOverriding($)
9223{
9224 my $LibVersion = $_[0];
9225 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009226 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009227 foreach my $ClassName (@Classes)
9228 {
9229 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
9230 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009231 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
9232 { # pure virtuals
9233 next;
9234 }
9235 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
9236 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009237 {
9238 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
9239 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
9240 { # both overridden virtual methods
9241 # and implemented pure virtual methods
9242 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
9243 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
9244 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
9245 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009246 }
9247 }
9248 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
9249 delete($VirtualTable{$LibVersion}{$ClassName});
9250 }
9251 }
9252}
9253
9254sub setVirtFuncPositions($)
9255{
9256 my $LibVersion = $_[0];
9257 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
9258 {
9259 my ($Num, $RelPos, $AbsNum) = (1, 0, 1);
9260 foreach my $VirtFunc (sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})}
9261 sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
9262 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009263 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}=$Num++;
9264
9265 # set relative positions
9266 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
9267 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
9268 { # relative position excluding added and removed virtual functions
9269 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
9270 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009271 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $RelPos++;
9272 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009273 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009274 }
9275 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009276 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009277 {
9278 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009279 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
9280 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc}=$AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009281 }
9282 }
9283}
9284
9285sub get_sub_classes($$$)
9286{
9287 my ($ClassId, $LibVersion, $Recursive) = @_;
9288 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
9289 my @Subs = ();
9290 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
9291 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009292 if($Recursive)
9293 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009294 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
9295 push(@Subs, $SubSubId);
9296 }
9297 }
9298 push(@Subs, $SubId);
9299 }
9300 return @Subs;
9301}
9302
9303sub get_base_classes($$$)
9304{
9305 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009306 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009307 return () if(not defined $ClassType{"Base"});
9308 my @Bases = ();
9309 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
9310 keys(%{$ClassType{"Base"}}))
9311 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009312 if($Recursive)
9313 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009314 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
9315 push(@Bases, $SubBaseId);
9316 }
9317 }
9318 push(@Bases, $BaseId);
9319 }
9320 return @Bases;
9321}
9322
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009323sub getVTable_Model($$)
9324{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009325 my ($ClassId, $LibVersion) = @_;
9326 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
9327 my @Elements = ();
9328 foreach my $BaseId (@Bases, $ClassId)
9329 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009330 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009331 {
9332 if(defined $VirtualTable{$LibVersion}{$BName})
9333 {
9334 my @VFunctions = keys(%{$VirtualTable{$LibVersion}{$BName}});
9335 @VFunctions = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFunctions;
9336 foreach my $VFunc (@VFunctions) {
9337 push(@Elements, $VFunc);
9338 }
9339 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009340 }
9341 }
9342 return @Elements;
9343}
9344
9345sub getVShift($$)
9346{
9347 my ($ClassId, $LibVersion) = @_;
9348 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
9349 my $VShift = 0;
9350 foreach my $BaseId (@Bases)
9351 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009352 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009353 {
9354 if(defined $VirtualTable{$LibVersion}{$BName}) {
9355 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
9356 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009357 }
9358 }
9359 return $VShift;
9360}
9361
9362sub getShift($$)
9363{
9364 my ($ClassId, $LibVersion) = @_;
9365 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
9366 my $Shift = 0;
9367 foreach my $BaseId (@Bases)
9368 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009369 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009370 {
9371 if($Size!=1)
9372 { # not empty base class
9373 $Shift+=$Size;
9374 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009375 }
9376 }
9377 return $Shift;
9378}
9379
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009380sub getVTable_Size($$)
9381{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009382 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009383 my $Size = 0;
9384 # three approaches
9385 if(not $Size)
9386 { # real size
9387 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
9388 $Size = keys(%VTable);
9389 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009390 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009391 if(not $Size)
9392 { # shared library symbol size
9393 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
9394 $Size /= $WORD_SIZE{$LibVersion};
9395 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009396 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009397 if(not $Size)
9398 { # model size
9399 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
9400 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
9401 }
9402 }
9403 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009404}
9405
9406sub isCopyingClass($$)
9407{
9408 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009409 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009410}
9411
9412sub isLeafClass($$)
9413{
9414 my ($ClassId, $LibVersion) = @_;
9415 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
9416}
9417
9418sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009419{ # check structured type for public fields
9420 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009421}
9422
9423sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009424{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009425 my ($TypePtr, $Skip, $Start, $End) = @_;
9426 return 0 if(not $TypePtr);
9427 if($End==-1) {
9428 $End = keys(%{$TypePtr->{"Memb"}})-1;
9429 }
9430 foreach my $MemPos (keys(%{$TypePtr->{"Memb"}}))
9431 {
9432 if($Skip and $Skip->{$MemPos})
9433 { # skip removed/added fields
9434 next;
9435 }
9436 if(int($MemPos)>=$Start and int($MemPos)<=$End)
9437 {
9438 if(isPublic($TypePtr, $MemPos)) {
9439 return ($MemPos+1);
9440 }
9441 }
9442 }
9443 return 0;
9444}
9445
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009446sub isReserved($)
9447{ # reserved fields == private
9448 my $MName = $_[0];
9449 if($MName=~/reserved|padding|f_spare/i) {
9450 return 1;
9451 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009452 if($MName=~/\A[_]*(spare|pad|unused)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009453 return 1;
9454 }
9455 if($MName=~/(pad\d+)/i) {
9456 return 1;
9457 }
9458 return 0;
9459}
9460
9461sub isPublic($$)
9462{
9463 my ($TypePtr, $FieldPos) = @_;
9464 return 0 if(not $TypePtr);
9465 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
9466 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
9467 if(not $TypePtr->{"Memb"}{$FieldPos}{"access"})
9468 { # by name in C language
9469 # FIXME: add other methods to detect private members
9470 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
9471 if($MName=~/priv|abidata|parent_object/i)
9472 { # C-styled private data
9473 return 0;
9474 }
9475 if(lc($MName) eq "abi")
9476 { # ABI information/reserved field
9477 return 0;
9478 }
9479 if(isReserved($MName))
9480 { # reserved fields
9481 return 0;
9482 }
9483 return 1;
9484 }
9485 elsif($TypePtr->{"Memb"}{$FieldPos}{"access"} ne "private")
9486 { # by access in C++ language
9487 return 1;
9488 }
9489 return 0;
9490}
9491
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009492sub getVTable_Real($$)
9493{
9494 my ($ClassName, $LibVersion) = @_;
9495 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9496 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009497 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009498 if(defined $Type{"VTable"}) {
9499 return %{$Type{"VTable"}};
9500 }
9501 }
9502 return ();
9503}
9504
9505sub cmpVTables($)
9506{
9507 my $ClassName = $_[0];
9508 my $Res = cmpVTables_Real($ClassName, 1);
9509 if($Res==-1) {
9510 $Res = cmpVTables_Model($ClassName);
9511 }
9512 return $Res;
9513}
9514
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009515sub cmpVTables_Model($)
9516{
9517 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009518 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009519 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009520 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009521 return 1;
9522 }
9523 }
9524 return 0;
9525}
9526
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009527sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009528{
9529 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009530 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
9531 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009532 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009533 my %VTable_Old = getVTable_Real($ClassName, 1);
9534 my %VTable_New = getVTable_Real($ClassName, 2);
9535 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009536 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009537 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009538 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009539 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009540 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
9541 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009542 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009543 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009544 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009545 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009546 my $Entry1 = $VTable_Old{$Offset};
9547 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009548 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009549 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009550 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009551 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009552 $Entry1 = simpleVEntry($Entry1);
9553 $Entry2 = simpleVEntry($Entry2);
9554 if($Entry1 ne $Entry2)
9555 { # register as changed
9556 if($Entry1=~/::([^:]+)\Z/)
9557 {
9558 my $M1 = $1;
9559 if($Entry2=~/::([^:]+)\Z/)
9560 {
9561 my $M2 = $1;
9562 if($M1 eq $M2)
9563 { # overridden
9564 next;
9565 }
9566 }
9567 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009568 if(differentDumps("G"))
9569 {
9570 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
9571 {
9572 # GCC 4.6.1: -0x00000000000000010
9573 # GCC 4.7.0: -16
9574 next;
9575 }
9576 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009577 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009578 }
9579 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009580 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009581}
9582
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009583sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009584{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009585 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009586 foreach my $ClassName (keys(%{$VirtualTable{1}}))
9587 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009588 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009589 { # already registered
9590 next;
9591 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009592 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009593 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009594 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009595 foreach my $Symbol (@Affected)
9596 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009597 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009598 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009599 "Target"=>$ClassName);
9600 }
9601 }
9602 }
9603}
9604
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009605sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009606{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009607 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009608 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009609 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009610 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009611 next if(not $ClassId);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009612 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009613 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009614 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009615 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009616 if($TName_Tid{1}{$ClassName}
9617 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009618 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009619 if(defined $CompleteSignature{1}{$Symbol}
9620 and $CompleteSignature{1}{$Symbol}{"Virt"})
9621 { # override some method in v.1
9622 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009623 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009624 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009625 }
9626 }
9627 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009628 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009629 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009630 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009631 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009632 if($TName_Tid{2}{$ClassName}
9633 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009634 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009635 if(defined $CompleteSignature{2}{$Symbol}
9636 and $CompleteSignature{2}{$Symbol}{"Virt"})
9637 { # override some method in v.2
9638 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009639 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009640 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009641 }
9642 }
9643 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009644 if($Level eq "Binary")
9645 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009646 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009647 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
9648 { # check replacements, including pure virtual methods
9649 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
9650 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009651 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009652 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
9653 if($AddedPos==$RemovedPos)
9654 {
9655 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
9656 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
9657 last; # other methods will be reported as "added" or "removed"
9658 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009659 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009660 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
9661 {
9662 if(lc($AddedVFunc) eq lc($RemovedVFunc))
9663 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009664 next;
9665 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009666 my $ProblemType = "Virtual_Replacement";
9667 my @Affected = ($RemovedVFunc);
9668 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
9669 { # pure methods
9670 if(not isUsedClass($ClassId, 1, $Level))
9671 { # not a parameter of some exported method
9672 next;
9673 }
9674 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009675
9676 # affected all methods (both virtual and non-virtual ones)
9677 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
9678 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009679 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009680 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009681 foreach my $AffectedInt (@Affected)
9682 {
9683 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
9684 { # affected exported methods only
9685 next;
9686 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009687 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
9688 next;
9689 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009690 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
9691 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009692 "Target"=>get_Signature($AddedVFunc, 2),
9693 "Old_Value"=>get_Signature($RemovedVFunc, 1));
9694 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009695 }
9696 }
9697 }
9698 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009699 if(not checkDump(1, "2.0")
9700 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009701 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009702 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009703 return;
9704 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009705 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009706 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009707 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009708 next if(not $ClassId_Old);
9709 if(not isCreatable($ClassId_Old, 1))
9710 { # skip classes without public constructors (including auto-generated)
9711 # example: class has only a private exported or private inline constructor
9712 next;
9713 }
9714 if($ClassName=~/>/)
9715 { # skip affected template instances
9716 next;
9717 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009718 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009719 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009720 if(not $ClassId_New) {
9721 next;
9722 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009723 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009724 if($Class_New{"Type"}!~/Class|Struct/)
9725 { # became typedef
9726 if($Level eq "Binary") {
9727 next;
9728 }
9729 if($Level eq "Source")
9730 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009731 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009732 if($Class_New{"Type"}!~/Class|Struct/) {
9733 next;
9734 }
9735 $ClassId_New = $Class_New{"Tid"};
9736 }
9737 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009738 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
9739 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 +04009740
9741 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
9742 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
9743
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009744 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009745 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
9746 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009747 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
9748 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009749 my $Shift_Old = getShift($ClassId_Old, 1);
9750 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009751 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009752 my ($Added, $Removed) = (0, 0);
9753 my @StableBases_Old = ();
9754 foreach my $BaseId (@Bases_Old)
9755 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009756 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009757 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009758 push(@StableBases_Old, $BaseId);
9759 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009760 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009761 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009762 { # removed base
9763 # excluding namespace::SomeClass to SomeClass renaming
9764 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009765 if($Level eq "Binary")
9766 { # Binary-level
9767 if($Shift_Old ne $Shift_New)
9768 { # affected fields
9769 if(havePubFields(\%Class_Old)) {
9770 $ProblemKind .= "_And_Shift";
9771 }
9772 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
9773 $ProblemKind .= "_And_Size";
9774 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009775 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009776 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
9777 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009778 { # affected v-table
9779 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009780 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009781 }
9782 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009783 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009784 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
9785 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009786 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
9787 {
9788 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
9789 if($ProblemKind=~/VTable/) {
9790 $VTableChanged_M{$SubName}=1;
9791 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009792 }
9793 }
9794 foreach my $Interface (@Affected)
9795 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009796 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
9797 next;
9798 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009799 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009800 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009801 "Target"=>$BaseName,
9802 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
9803 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
9804 "Shift"=>abs($Shift_New-$Shift_Old) );
9805 }
9806 $Removed+=1;
9807 }
9808 }
9809 my @StableBases_New = ();
9810 foreach my $BaseId (@Bases_New)
9811 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009812 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009813 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009814 push(@StableBases_New, $BaseId);
9815 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009816 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009817 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009818 { # added base
9819 # excluding namespace::SomeClass to SomeClass renaming
9820 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009821 if($Level eq "Binary")
9822 { # Binary-level
9823 if($Shift_Old ne $Shift_New)
9824 { # affected fields
9825 if(havePubFields(\%Class_Old)) {
9826 $ProblemKind .= "_And_Shift";
9827 }
9828 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
9829 $ProblemKind .= "_And_Size";
9830 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009831 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009832 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
9833 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009834 { # affected v-table
9835 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009836 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009837 }
9838 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009839 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009840 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
9841 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009842 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
9843 {
9844 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
9845 if($ProblemKind=~/VTable/) {
9846 $VTableChanged_M{$SubName}=1;
9847 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009848 }
9849 }
9850 foreach my $Interface (@Affected)
9851 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009852 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
9853 next;
9854 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009855 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009856 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009857 "Target"=>$BaseName,
9858 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
9859 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
9860 "Shift"=>abs($Shift_New-$Shift_Old) );
9861 }
9862 $Added+=1;
9863 }
9864 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009865 if($Level eq "Binary")
9866 { # Binary-level
9867 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009868 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
9869 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009870 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009871 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009872 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009873 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009874 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009875 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
9876 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009877 if($NewPos!=$OldPos)
9878 { # changed position of the base class
9879 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009880 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009881 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
9882 next;
9883 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009884 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
9885 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009886 "Target"=>$BaseName,
9887 "Old_Value"=>$OldPos-1,
9888 "New_Value"=>$NewPos-1 );
9889 }
9890 }
9891 if($Class_Old{"Base"}{$BaseId}{"virtual"}
9892 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
9893 { # became non-virtual base
9894 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
9895 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009896 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
9897 next;
9898 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009899 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
9900 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009901 "Target"=>$BaseName );
9902 }
9903 }
9904 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
9905 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
9906 { # became virtual base
9907 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
9908 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009909 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
9910 next;
9911 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009912 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
9913 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009914 "Target"=>$BaseName );
9915 }
9916 }
9917 }
9918 }
9919 # detect size changes in base classes
9920 if($Shift_Old!=$Shift_New)
9921 { # size of allocable class
9922 foreach my $BaseId (@StableBases_Old)
9923 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009924 my %BaseType = get_Type($BaseId, 1);
9925 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009926 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009927 if($Size_Old ne $Size_New
9928 and $Size_Old and $Size_New)
9929 {
9930 my $ProblemType = "";
9931 if(isCopyingClass($BaseId, 1)) {
9932 $ProblemType = "Size_Of_Copying_Class";
9933 }
9934 elsif($AllocableClass{1}{$BaseType{"Name"}})
9935 {
9936 if($Size_New>$Size_Old)
9937 { # increased size
9938 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009939 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009940 else
9941 { # decreased size
9942 $ProblemType = "Size_Of_Allocable_Class_Decreased";
9943 if(not havePubFields(\%Class_Old))
9944 { # affected class has no public members
9945 next;
9946 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009947 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009948 }
9949 next if(not $ProblemType);
9950 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
9951 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009952 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
9953 next;
9954 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009955 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
9956 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009957 "Target"=>$BaseType{"Name"},
9958 "Old_Size"=>$Size_Old*$BYTE_SIZE,
9959 "New_Size"=>$Size_New*$BYTE_SIZE );
9960 }
9961 }
9962 }
9963 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009964 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009965 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009966 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009967 { # compare virtual tables size in base classes
9968 my $VShift_Old = getVShift($ClassId_Old, 1);
9969 my $VShift_New = getVShift($ClassId_New, 2);
9970 if($VShift_Old ne $VShift_New)
9971 { # changes in the base class or changes in the list of base classes
9972 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
9973 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
9974 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009975 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009976 foreach my $BaseId (@AllBases_Old)
9977 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009978 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009979 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009980 { # lost base
9981 next;
9982 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009983 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
9984 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009985 if($VSize_Old!=$VSize_New)
9986 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009987 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009988 { # TODO: affected non-virtual methods?
9989 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009990 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
9991 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009992 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009993 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009994 { # skip interfaces that have not changed the absolute virtual position
9995 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009996 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009997 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
9998 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009999 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010000 $VTableChanged_M{$BaseType{"Name"}} = 1;
10001 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010002 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
10003 { # the reason of the layout change: added virtual functions
10004 next if($VirtualReplacement{$VirtFunc});
10005 my $ProblemType = "Added_Virtual_Method";
10006 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
10007 $ProblemType = "Added_Pure_Virtual_Method";
10008 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010009 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010010 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010011 "Target"=>get_Signature($VirtFunc, 2) );
10012 }
10013 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
10014 { # the reason of the layout change: removed virtual functions
10015 next if($VirtualReplacement{$VirtFunc});
10016 my $ProblemType = "Removed_Virtual_Method";
10017 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
10018 $ProblemType = "Removed_Pure_Virtual_Method";
10019 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010020 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010021 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010022 "Target"=>get_Signature($VirtFunc, 1) );
10023 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010024 }
10025 }
10026 }
10027 }
10028 }
10029 }
10030 }
10031}
10032
10033sub isCreatable($$)
10034{
10035 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010036 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010037 or isCopyingClass($ClassId, $LibVersion)) {
10038 return 1;
10039 }
10040 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10041 { # Fix for incomplete data: if this class has
10042 # a base class then it should also has a constructor
10043 return 1;
10044 }
10045 if($ReturnedClass{$LibVersion}{$ClassId})
10046 { # returned by some method of this class
10047 # or any other class
10048 return 1;
10049 }
10050 return 0;
10051}
10052
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010053sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010054{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010055 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010056 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
10057 { # parameter of some exported method
10058 return 1;
10059 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010060 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
10061 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010062 { # method from target class
10063 return 1;
10064 }
10065 return 0;
10066}
10067
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010068sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010069{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010070 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010071 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010072 # - virtual
10073 # - pure-virtual
10074 # - non-virtual
10075 if($CompleteSignature{1}{$Interface}{"Data"})
10076 { # global data is not affected
10077 return;
10078 }
10079 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010080 if(not $Class_Id) {
10081 return;
10082 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010083 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010084 if(cmpVTables_Real($CName, 1)==0)
10085 { # no changes
10086 return;
10087 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010088 $CheckedTypes{$Level}{$CName} = 1;
10089 if($Level eq "Binary")
10090 { # Binary-level
10091 if($CompleteSignature{1}{$Interface}{"PureVirt"}
10092 and not isUsedClass($Class_Id, 1, $Level))
10093 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010094 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010095 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010096 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010097 }
10098 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
10099 {
10100 if(defined $VirtualTable{2}{$CName}{$Func}
10101 and defined $CompleteSignature{2}{$Func})
10102 {
10103 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
10104 and $CompleteSignature{2}{$Func}{"PureVirt"})
10105 { # became pure virtual
10106 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
10107 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010108 "Target"=>get_Signature_M($Func, 1) );
10109 $VTableChanged_M{$CName} = 1;
10110 }
10111 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
10112 and not $CompleteSignature{2}{$Func}{"PureVirt"})
10113 { # became non-pure virtual
10114 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
10115 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010116 "Target"=>get_Signature_M($Func, 1) );
10117 $VTableChanged_M{$CName} = 1;
10118 }
10119 }
10120 }
10121 if($Level eq "Binary")
10122 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010123 # check virtual table structure
10124 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
10125 {
10126 next if($Interface eq $AddedVFunc);
10127 next if($VirtualReplacement{$AddedVFunc});
10128 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
10129 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
10130 { # pure virtual methods affect all others (virtual and non-virtual)
10131 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010132 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010133 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010134 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010135 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010136 elsif(not defined $VirtualTable{1}{$CName}
10137 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010138 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010139 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010140 { # became polymorphous class, added v-table pointer
10141 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010142 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010143 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010144 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010145 }
10146 else
10147 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010148 my $VSize_Old = getVTable_Size($CName, 1);
10149 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010150 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010151 if(isCopyingClass($Class_Id, 1))
10152 { # class has no constructors and v-table will be copied by applications, this may affect all methods
10153 my $ProblemType = "Added_Virtual_Method";
10154 if(isLeafClass($Class_Id, 1)) {
10155 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
10156 }
10157 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10158 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010159 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010160 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010161 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010162 else
10163 {
10164 my $ProblemType = "Added_Virtual_Method";
10165 if(isLeafClass($Class_Id, 1)) {
10166 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
10167 }
10168 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10169 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010170 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010171 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010172 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010173 }
10174 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010175 elsif($CompleteSignature{1}{$Interface}{"Virt"}
10176 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010177 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010178 if(defined $VirtualTable{1}{$CName}
10179 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010180 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010181 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
10182 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
10183 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010184 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010185 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
10186 foreach my $ASymbol (@Affected)
10187 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010188 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
10189 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010190 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010191 next;
10192 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010193 }
10194 $CheckedSymbols{$Level}{$ASymbol} = 1;
10195 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
10196 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010197 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010198 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010199 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010200 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010201 }
10202 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010203 else {
10204 # safe
10205 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010206 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010207 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
10208 {
10209 next if($VirtualReplacement{$RemovedVFunc});
10210 if($RemovedVFunc eq $Interface
10211 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10212 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010213 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010214 next;
10215 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010216 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010217 { # became non-polymorphous class, removed v-table pointer
10218 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
10219 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010220 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010221 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010222 }
10223 elsif($CompleteSignature{1}{$Interface}{"Virt"}
10224 or $CompleteSignature{1}{$Interface}{"PureVirt"})
10225 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010226 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010227 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010228 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
10229 next;
10230 }
10231 my $VPos_New = -1;
10232 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010233 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010234 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
10235 }
10236 else
10237 {
10238 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010239 next;
10240 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010241 }
10242 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
10243 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
10244 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
10245 {
10246 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
10247 foreach my $ASymbol (@Affected)
10248 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010249 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
10250 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010251 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010252 next;
10253 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010254 }
10255 my $ProblemType = "Removed_Virtual_Method";
10256 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
10257 $ProblemType = "Removed_Pure_Virtual_Method";
10258 }
10259 $CheckedSymbols{$Level}{$ASymbol} = 1;
10260 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
10261 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010262 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010263 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010264 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010265 }
10266 }
10267 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010268 }
10269 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010270 else
10271 { # Source-level
10272 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010273 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010274 next if($Interface eq $AddedVFunc);
10275 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010276 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010277 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
10278 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010279 "Target"=>get_Signature($AddedVFunc, 2) );
10280 }
10281 }
10282 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
10283 {
10284 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10285 {
10286 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
10287 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010288 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010289 }
10290 }
10291 }
10292}
10293
10294sub find_MemberPair_Pos_byName($$)
10295{
10296 my ($Member_Name, $Pair_Type) = @_;
10297 $Member_Name=~s/\A[_]+|[_]+\Z//g;
10298 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
10299 {
10300 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
10301 {
10302 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
10303 $Name=~s/\A[_]+|[_]+\Z//g;
10304 if($Name eq $Member_Name) {
10305 return $MemberPair_Pos;
10306 }
10307 }
10308 }
10309 return "lost";
10310}
10311
10312sub find_MemberPair_Pos_byVal($$)
10313{
10314 my ($Member_Value, $Pair_Type) = @_;
10315 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
10316 {
10317 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
10318 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
10319 return $MemberPair_Pos;
10320 }
10321 }
10322 return "lost";
10323}
10324
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010325my %Severity_Val=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010326 "High"=>3,
10327 "Medium"=>2,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010328 "Low"=>1,
10329 "Safe"=>-1
10330);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010331
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010332sub maxSeverity($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010333{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010334 my ($S1, $S2) = @_;
10335 if(cmpSeverities($S1, $S2)) {
10336 return $S1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010337 }
10338 else {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010339 return $S2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010340 }
10341}
10342
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010343sub cmpSeverities($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010344{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010345 my ($S1, $S2) = @_;
10346 if(not $S1) {
10347 return 0;
10348 }
10349 elsif(not $S2) {
10350 return 1;
10351 }
10352 return ($Severity_Val{$S1}>$Severity_Val{$S2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010353}
10354
10355sub getProblemSeverity($$)
10356{
10357 my ($Level, $Kind) = @_;
10358 return $CompatRules{$Level}{$Kind}{"Severity"};
10359}
10360
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010361sub isRecurType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010362{
10363 foreach (@RecurTypes)
10364 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010365 if( $_->{"T1"} eq $_[0]
10366 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010367 {
10368 return 1;
10369 }
10370 }
10371 return 0;
10372}
10373
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010374sub pushType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010375{
10376 my %TypeIDs=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010377 "T1" => $_[0], #Tid1
10378 "T2" => $_[1] #Tid2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010379 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010380 push(@RecurTypes, \%TypeIDs);
10381}
10382
10383sub isRenamed($$$$$)
10384{
10385 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
10386 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
10387 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010388 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010389 if(not defined $Type2->{"Memb"}{$MemPos}) {
10390 return "";
10391 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010392 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010393 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010394
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010395 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
10396 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010397 if($MemberPair_Pos_Rev eq "lost")
10398 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010399 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
10400 { # base type match
10401 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010402 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010403 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
10404 { # exact type match
10405 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010406 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010407 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
10408 { # size match
10409 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010410 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010411 if(isReserved($Pair_Name))
10412 { # reserved fields
10413 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010414 }
10415 }
10416 return "";
10417}
10418
10419sub isLastElem($$)
10420{
10421 my ($Pos, $TypeRef) = @_;
10422 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
10423 if($Name=~/last|count|max|total/i)
10424 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
10425 return 1;
10426 }
10427 elsif($Name=~/END|NLIMITS\Z/)
10428 { # __RLIMIT_NLIMITS
10429 return 1;
10430 }
10431 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
10432 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
10433 { # NImageFormats, NColorRoles
10434 return 1;
10435 }
10436 return 0;
10437}
10438
10439sub nonComparable($$)
10440{
10441 my ($T1, $T2) = @_;
10442 if($T1->{"Name"} ne $T2->{"Name"}
10443 and not isAnon($T1->{"Name"})
10444 and not isAnon($T2->{"Name"}))
10445 { # different names
10446 if($T1->{"Type"} ne "Pointer"
10447 or $T2->{"Type"} ne "Pointer")
10448 { # compare base types
10449 return 1;
10450 }
10451 if($T1->{"Name"}!~/\Avoid\s*\*/
10452 and $T2->{"Name"}=~/\Avoid\s*\*/)
10453 {
10454 return 1;
10455 }
10456 }
10457 elsif($T1->{"Type"} ne $T2->{"Type"})
10458 { # different types
10459 if($T1->{"Type"} eq "Class"
10460 and $T2->{"Type"} eq "Struct")
10461 { # "class" to "struct"
10462 return 0;
10463 }
10464 elsif($T2->{"Type"} eq "Class"
10465 and $T1->{"Type"} eq "Struct")
10466 { # "struct" to "class"
10467 return 0;
10468 }
10469 else
10470 { # "class" to "enum"
10471 # "union" to "class"
10472 # ...
10473 return 1;
10474 }
10475 }
10476 return 0;
10477}
10478
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010479sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010480{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010481 my ($Type1_Id, $Type2_Id, $Level) = @_;
10482 return () if(not $Type1_Id or not $Type2_Id);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010483 my (%Sub_SubProblems, %SubProblems) = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010484 if($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010485 { # already merged
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010486 return %{$Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010487 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010488 my %Type1 = get_Type($Type1_Id, 1);
10489 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010490 if(not $Type1{"Name"} or not $Type2{"Name"}) {
10491 return ();
10492 }
10493 $CheckedTypes{$Level}{$Type1{"Name"}}=1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010494 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
10495 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010496 $CheckedTypes{$Level}{$Type1_Pure{"Name"}}=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010497 if(not $Type1_Pure{"Size"} or not $Type2_Pure{"Size"})
10498 { # including a case when "class Class { ... };" changed to "class Class;"
10499 return ();
10500 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010501 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010502 { # skip recursive declarations
10503 return ();
10504 }
10505 return () if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
10506 return () if($SkipTypes{1}{$Type1_Pure{"Name"}});
10507 return () if($SkipTypes{1}{$Type1{"Name"}});
10508
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010509 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
10510 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010511 if(not $UseOldDumps and %Typedef_1 and %Typedef_2
10512 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
10513 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010514 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010515 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
10516 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010517 if($Base_1{"Name"} ne $Base_2{"Name"})
10518 {
10519 if(differentDumps("G")
10520 or differentDumps("V"))
10521 { # different GCC versions or different dumps
10522 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
10523 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
10524 # std::__va_list and __va_list
10525 $Base_1{"Name"}=~s/\A(\w+::)+//;
10526 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010527 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
10528 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010529 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010530 }
10531 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
10532 and $Base_1{"Name"} ne $Base_2{"Name"})
10533 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010534 if($Level eq "Binary"
10535 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010536 {
10537 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
10538 "Target"=>$Typedef_1{"Name"},
10539 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010540 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
10541 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
10542 }
10543 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
10544 "Target"=>$Typedef_1{"Name"},
10545 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010546 "Old_Value"=>$Base_1{"Name"},
10547 "New_Value"=>$Base_2{"Name"} );
10548 }
10549 }
10550 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
10551 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010552 my $TT1 = $Type1_Pure{"Type"};
10553 my $TT2 = $Type2_Pure{"Type"};
10554
10555 if($TT1 ne $TT2
10556 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010557 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010558 my $Short1 = $Type1_Pure{"Name"};
10559 my $Short2 = $Type2_Pure{"Name"};
10560
10561 $Short1=~s/\A\Q$TT1\E //ig;
10562 $Short2=~s/\A\Q$TT2\E //ig;
10563
10564 if($Short1 eq $Short2)
10565 {
10566 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
10567 "Target"=>$Type1_Pure{"Name"},
10568 "Type_Name"=>$Type1_Pure{"Name"},
10569 "Old_Value"=>lc($Type1_Pure{"Type"}),
10570 "New_Value"=>lc($Type2_Pure{"Type"}) );
10571 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010572 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010573 %{$Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id}} = %SubProblems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010574 return %SubProblems;
10575 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010576 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010577 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
10578 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
10579 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
10580 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010581 if($Level eq "Binary"
10582 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010583 {
10584 my $ProblemKind = "DataType_Size";
10585 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010586 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010587 {
10588 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
10589 $ProblemKind = "Size_Of_Copying_Class";
10590 }
10591 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
10592 {
10593 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
10594 $ProblemKind = "Size_Of_Allocable_Class_Increased";
10595 }
10596 else {
10597 # descreased size of allocable class
10598 # it has no special effects
10599 }
10600 }
10601 }
10602 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
10603 "Target"=>$Type1_Pure{"Name"},
10604 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010605 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
10606 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE,
10607 "InitialType_Type"=>$Type1_Pure{"Type"} );
10608 }
10609 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010610 if(defined $Type1_Pure{"BaseType"} and $Type1_Pure{"BaseType"}{"Tid"}
10611 and defined $Type2_Pure{"BaseType"} and $Type2_Pure{"BaseType"}{"Tid"})
10612 { # checking base types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010613 %Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}{"Tid"}, $Type2_Pure{"BaseType"}{"Tid"}, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010614 foreach my $Sub_SubProblemType (keys(%Sub_SubProblems))
10615 {
10616 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems{$Sub_SubProblemType}}))
10617 {
10618 foreach my $Attr (keys(%{$Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}})) {
10619 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}{$Attr} = $Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}{$Attr};
10620 }
10621 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}{"InitialType_Type"} = $Type1_Pure{"Type"};
10622 }
10623 }
10624 }
10625 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
10626 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
10627 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
10628 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
10629 { # detect removed and renamed fields
10630 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
10631 next if(not $Member_Name);
10632 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);
10633 if($MemberPair_Pos eq "lost")
10634 {
10635 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
10636 {
10637 if(isUnnamed($Member_Name))
10638 { # support for old-version dumps
10639 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010640 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010641 next;
10642 }
10643 }
10644 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
10645 { # renamed
10646 $RenamedField{$Member_Pos}=$RenamedTo;
10647 $RenamedField_Rev{$NameToPosB{$RenamedTo}}=$Member_Name;
10648 }
10649 else
10650 { # removed
10651 $RemovedField{$Member_Pos}=1;
10652 }
10653 }
10654 elsif($Type1_Pure{"Type"} eq "Enum")
10655 {
10656 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
10657 next if($Member_Value1 eq "");
10658 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
10659 if($MemberPair_Pos ne "lost")
10660 { # renamed
10661 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
10662 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
10663 if($MemberPair_Pos_Rev eq "lost")
10664 {
10665 $RenamedField{$Member_Pos}=$RenamedTo;
10666 $RenamedField_Rev{$NameToPosB{$RenamedTo}}=$Member_Name;
10667 }
10668 else {
10669 $RemovedField{$Member_Pos}=1;
10670 }
10671 }
10672 else
10673 { # removed
10674 $RemovedField{$Member_Pos}=1;
10675 }
10676 }
10677 }
10678 else
10679 { # related
10680 $RelatedField{$Member_Pos} = $MemberPair_Pos;
10681 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
10682 }
10683 }
10684 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
10685 { # detect added fields
10686 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
10687 next if(not $Member_Name);
10688 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);
10689 if($MemberPair_Pos eq "lost")
10690 {
10691 if(isUnnamed($Member_Name))
10692 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010693 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010694 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010695 next;
10696 }
10697 }
10698 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
10699 {
10700 if(not $RenamedField_Rev{$Member_Pos})
10701 { # added
10702 $AddedField{$Member_Pos}=1;
10703 }
10704 }
10705 }
10706 }
10707 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
10708 { # detect moved fields
10709 my (%RelPos, %RelPosName, %AbsPos) = ();
10710 my $Pos = 0;
10711 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
10712 { # relative positions in 1st version
10713 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
10714 next if(not $Member_Name);
10715 if(not $RemovedField{$Member_Pos})
10716 { # old type without removed fields
10717 $RelPos{1}{$Member_Name}=$Pos;
10718 $RelPosName{1}{$Pos} = $Member_Name;
10719 $AbsPos{1}{$Pos++} = $Member_Pos;
10720 }
10721 }
10722 $Pos = 0;
10723 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
10724 { # relative positions in 2nd version
10725 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
10726 next if(not $Member_Name);
10727 if(not $AddedField{$Member_Pos})
10728 { # new type without added fields
10729 $RelPos{2}{$Member_Name}=$Pos;
10730 $RelPosName{2}{$Pos} = $Member_Name;
10731 $AbsPos{2}{$Pos++} = $Member_Pos;
10732 }
10733 }
10734 foreach my $Member_Name (keys(%{$RelPos{1}}))
10735 {
10736 my $RPos1 = $RelPos{1}{$Member_Name};
10737 my $AbsPos1 = $NameToPosA{$Member_Name};
10738 my $Member_Name2 = $Member_Name;
10739 if(my $RenamedTo = $RenamedField{$AbsPos1})
10740 { # renamed
10741 $Member_Name2 = $RenamedTo;
10742 }
10743 my $RPos2 = $RelPos{2}{$Member_Name2};
10744 if($RPos2 ne "" and $RPos1 ne $RPos2)
10745 { # different relative positions
10746 my $AbsPos2 = $NameToPosB{$Member_Name2};
10747 if($AbsPos1 ne $AbsPos2)
10748 { # different absolute positions
10749 my $ProblemType = "Moved_Field";
10750 if(not isPublic(\%Type1_Pure, $AbsPos1))
10751 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010752 if($Level eq "Source") {
10753 next;
10754 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010755 $ProblemType = "Moved_Private_Field";
10756 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010757 if($Level eq "Binary"
10758 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010759 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010760 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010761 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010762 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010763 if($MemSize1 ne $MemSize2) {
10764 $ProblemType .= "_And_Size";
10765 }
10766 }
10767 if($ProblemType eq "Moved_Private_Field") {
10768 next;
10769 }
10770 %{$SubProblems{$ProblemType}{$Member_Name}}=(
10771 "Target"=>$Member_Name,
10772 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010773 "Old_Value"=>$RPos1,
10774 "New_Value"=>$RPos2 );
10775 }
10776 }
10777 }
10778 }
10779 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010780 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010781 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
10782 next if(not $Member_Name);
10783 if(my $RenamedTo = $RenamedField{$Member_Pos})
10784 { # renamed
10785 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
10786 {
10787 if(isPublic(\%Type1_Pure, $Member_Pos))
10788 {
10789 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
10790 "Target"=>$Member_Name,
10791 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010792 "Old_Value"=>$Member_Name,
10793 "New_Value"=>$RenamedTo );
10794 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010795 elsif(isReserved($Member_Name))
10796 {
10797 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
10798 "Target"=>$Member_Name,
10799 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010800 "Old_Value"=>$Member_Name,
10801 "New_Value"=>$RenamedTo );
10802 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010803 }
10804 elsif($Type1_Pure{"Type"} eq "Enum")
10805 {
10806 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
10807 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
10808 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010809 "Old_Value"=>$Member_Name,
10810 "New_Value"=>$RenamedTo );
10811 }
10812 }
10813 elsif($RemovedField{$Member_Pos})
10814 { # removed
10815 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
10816 {
10817 my $ProblemType = "Removed_Field";
10818 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010819 or isUnnamed($Member_Name))
10820 {
10821 if($Level eq "Source") {
10822 next;
10823 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010824 $ProblemType = "Removed_Private_Field";
10825 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010826 if($Level eq "Binary"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010827 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010828 {
10829 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
10830 { # affected fields
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010831 if(getOffset($MNum-1, \%Type1_Pure, $TypeInfo{1}, $WORD_SIZE{1})!=getOffset($RelatedField{$MNum-1}, \%Type2_Pure, $TypeInfo{2}, $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010832 { # changed offset
10833 $ProblemType .= "_And_Layout";
10834 }
10835 }
10836 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
10837 { # affected size
10838 $ProblemType .= "_And_Size";
10839 }
10840 }
10841 if($ProblemType eq "Removed_Private_Field") {
10842 next;
10843 }
10844 %{$SubProblems{$ProblemType}{$Member_Name}}=(
10845 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010846 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010847 }
10848 elsif($Type2_Pure{"Type"} eq "Union")
10849 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010850 if($Level eq "Binary"
10851 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010852 {
10853 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
10854 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010855 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010856 }
10857 else
10858 {
10859 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
10860 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010861 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010862 }
10863 }
10864 elsif($Type1_Pure{"Type"} eq "Enum")
10865 {
10866 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
10867 "Target"=>$Member_Name,
10868 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010869 "Old_Value"=>$Member_Name );
10870 }
10871 }
10872 else
10873 { # changed
10874 my $MemberPair_Pos = $RelatedField{$Member_Pos};
10875 if($Type1_Pure{"Type"} eq "Enum")
10876 {
10877 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
10878 next if($Member_Value1 eq "");
10879 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
10880 next if($Member_Value2 eq "");
10881 if($Member_Value1 ne $Member_Value2)
10882 {
10883 my $ProblemType = "Enum_Member_Value";
10884 if(isLastElem($Member_Pos, \%Type1_Pure)) {
10885 $ProblemType = "Enum_Last_Member_Value";
10886 }
10887 %{$SubProblems{$ProblemType}{$Member_Name}}=(
10888 "Target"=>$Member_Name,
10889 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010890 "Old_Value"=>$Member_Value1,
10891 "New_Value"=>$Member_Value2 );
10892 }
10893 }
10894 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
10895 {
10896 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
10897 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010898 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010899 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
10900 $SizeV1 = $BSize1;
10901 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010902 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010903 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
10904 $SizeV2 = $BSize2;
10905 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010906 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
10907 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010908 if($Level eq "Binary"
10909 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010910 {
10911 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
10912 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
10913 { # field size change (including anon-structures and unions)
10914 # - same types
10915 # - unnamed types
10916 # - bitfields
10917 my $ProblemType = "Field_Size";
10918 if(not isPublic(\%Type1_Pure, $Member_Pos)
10919 or isUnnamed($Member_Name))
10920 { # should not be accessed by applications, goes to "Low Severity"
10921 # example: "abidata" members in GStreamer types
10922 $ProblemType = "Private_".$ProblemType;
10923 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010924 if(not isMemPadded($Member_Pos, $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010925 { # check an effect
10926 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
10927 { # public fields after the current
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010928 if(getOffset($MNum-1, \%Type1_Pure, $TypeInfo{1}, $WORD_SIZE{1})!=getOffset($RelatedField{$MNum-1}, \%Type2_Pure, $TypeInfo{2}, $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010929 { # changed offset
10930 $ProblemType .= "_And_Layout";
10931 }
10932 }
10933 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
10934 $ProblemType .= "_And_Type_Size";
10935 }
10936 }
10937 if($ProblemType eq "Private_Field_Size")
10938 { # private field size with no effect
10939 $ProblemType = "";
10940 }
10941 if($ProblemType)
10942 { # register a problem
10943 %{$SubProblems{$ProblemType}{$Member_Name}}=(
10944 "Target"=>$Member_Name,
10945 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010946 "Old_Size"=>$SizeV1,
10947 "New_Size"=>$SizeV2);
10948 }
10949 }
10950 }
10951 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
10952 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
10953 { # do NOT check bitfield type changes
10954 next;
10955 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010956 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010957 {
10958 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
10959 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
10960 {
10961 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
10962 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010963 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010964 }
10965 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
10966 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
10967 {
10968 %{$SubProblems{"Field_Became_NonMutable"}{$Member_Name}}=(
10969 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010970 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010971 }
10972 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010973 %Sub_SubProblems = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010974 foreach my $ProblemType (keys(%Sub_SubProblems))
10975 {
10976 my $Old_Value = $Sub_SubProblems{$ProblemType}{"Old_Value"};
10977 my $New_Value = $Sub_SubProblems{$ProblemType}{"New_Value"};
10978 if($ProblemType eq "Field_Type"
10979 or $ProblemType eq "Field_Type_And_Size")
10980 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010981 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010982 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010983 if(my $RA = addedQual($Old_Value, $New_Value, "volatile"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010984 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010985 %{$Sub_SubProblems{"Field_Became_Volatile"}} = %{$Sub_SubProblems{$ProblemType}};
10986 if($Level eq "Source"
10987 and cmpBTypes($Old_Value, $New_Value, 1, 2)) {
10988 delete($Sub_SubProblems{$ProblemType});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010989 }
10990 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010991 elsif(my $RR = removedQual($Old_Value, $New_Value, "volatile"))
10992 {
10993 %{$Sub_SubProblems{"Field_Became_NonVolatile"}} = %{$Sub_SubProblems{$ProblemType}};
10994 if($Level eq "Source"
10995 and cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010996 delete($Sub_SubProblems{$ProblemType});
10997 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010998 }
10999 }
11000 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
11001 {
11002 if($RA==2) {
11003 %{$Sub_SubProblems{"Field_Added_Const"}} = %{$Sub_SubProblems{$ProblemType}};
11004 }
11005 else {
11006 %{$Sub_SubProblems{"Field_Became_Const"}} = %{$Sub_SubProblems{$ProblemType}};
11007 }
11008 if($Level eq "Source"
11009 and cmpBTypes($Old_Value, $New_Value, 1, 2)) {
11010 delete($Sub_SubProblems{$ProblemType});
11011 }
11012 }
11013 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
11014 {
11015 if($RR==2) {
11016 %{$Sub_SubProblems{"Field_Removed_Const"}} = %{$Sub_SubProblems{$ProblemType}};
11017 }
11018 else {
11019 %{$Sub_SubProblems{"Field_Became_NonConst"}} = %{$Sub_SubProblems{$ProblemType}};
11020 }
11021 if($Level eq "Source"
11022 and cmpBTypes($Old_Value, $New_Value, 1, 2)) {
11023 delete($Sub_SubProblems{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011024 }
11025 }
11026 }
11027 }
11028 foreach my $ProblemType (keys(%Sub_SubProblems))
11029 {
11030 my $ProblemType_Init = $ProblemType;
11031 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011032 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011033 if(not isPublic(\%Type1_Pure, $Member_Pos)
11034 or isUnnamed($Member_Name)) {
11035 $ProblemType = "Private_".$ProblemType;
11036 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011037 if(not isMemPadded($Member_Pos, $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011038 { # check an effect
11039 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
11040 { # public fields after the current
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011041 if(getOffset($MNum-1, \%Type1_Pure, $TypeInfo{1}, $WORD_SIZE{1})!=getOffset($RelatedField{$MNum-1}, \%Type2_Pure, $TypeInfo{2}, $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011042 { # changed offset
11043 $ProblemType .= "_And_Layout";
11044 }
11045 }
11046 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
11047 $ProblemType .= "_And_Type_Size";
11048 }
11049 }
11050 }
11051 else
11052 {
11053 if(not isPublic(\%Type1_Pure, $Member_Pos)
11054 or isUnnamed($Member_Name)) {
11055 next;
11056 }
11057 }
11058 if($ProblemType eq "Private_Field_Type_And_Size")
11059 { # private field change with no effect
11060 next;
11061 }
11062 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11063 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011064 "Type_Name"=>$Type1_Pure{"Name"});
11065
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011066 foreach my $Attr (keys(%{$Sub_SubProblems{$ProblemType_Init}}))
11067 { # other properties
11068 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubProblems{$ProblemType_Init}{$Attr};
11069 }
11070 }
11071 if(not isPublic(\%Type1_Pure, $Member_Pos))
11072 { # do NOT check internal type changes
11073 next;
11074 }
11075 if($MemberType1_Id and $MemberType2_Id)
11076 {# checking member type changes (replace)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011077 %Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011078 foreach my $Sub_SubProblemType (keys(%Sub_SubProblems))
11079 {
11080 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems{$Sub_SubProblemType}}))
11081 {
11082 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
11083 $SubProblems{$Sub_SubProblemType}{$NewLocation}{"IsInTypeInternals"}=1;
11084 foreach my $Attr (keys(%{$Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}})) {
11085 $SubProblems{$Sub_SubProblemType}{$NewLocation}{$Attr} = $Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}{$Attr};
11086 }
11087 if($Sub_SubLocation!~/\-\>/) {
11088 $SubProblems{$Sub_SubProblemType}{$NewLocation}{"Start_Type_Name"} = $MemberType1_Name;
11089 }
11090 }
11091 }
11092 }
11093 }
11094 }
11095 }
11096 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11097 { # checking added members, public and private
11098 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11099 next if(not $Member_Name);
11100 if($AddedField{$Member_Pos})
11101 { # added
11102 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11103 {
11104 my $ProblemType = "Added_Field";
11105 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011106 or isUnnamed($Member_Name))
11107 {
11108 if($Level eq "Source") {
11109 next;
11110 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011111 $ProblemType = "Added_Private_Field";
11112 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011113 if($Level eq "Binary"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011114 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011115 {
11116 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
11117 { # public fields after the current
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011118 if(getOffset($MNum-1, \%Type2_Pure, $TypeInfo{2}, $WORD_SIZE{2})!=getOffset($RelatedField_Rev{$MNum-1}, \%Type1_Pure, $TypeInfo{1}, $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011119 { # changed offset
11120 $ProblemType .= "_And_Layout";
11121 }
11122 }
11123 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
11124 $ProblemType .= "_And_Size";
11125 }
11126 }
11127 if($ProblemType eq "Added_Private_Field")
11128 { # skip added private fields
11129 next;
11130 }
11131 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11132 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011133 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011134 }
11135 elsif($Type2_Pure{"Type"} eq "Union")
11136 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011137 if($Level eq "Binary"
11138 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011139 {
11140 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
11141 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011142 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011143 }
11144 else
11145 {
11146 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
11147 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011148 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011149 }
11150 }
11151 elsif($Type2_Pure{"Type"} eq "Enum")
11152 {
11153 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
11154 next if($Member_Value eq "");
11155 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
11156 "Target"=>$Member_Name,
11157 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011158 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011159 }
11160 }
11161 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011162 %{$Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id}} = %SubProblems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011163 pop(@RecurTypes);
11164 return %SubProblems;
11165}
11166
11167sub isUnnamed($) {
11168 return $_[0]=~/\Aunnamed\d+\Z/;
11169}
11170
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011171sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011172{
11173 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011174 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
11175 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
11176 $TypeName = uncover_typedefs($TypeName, $LibVersion);
11177 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011178 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011179 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011180 }
11181 return $TypeName;
11182}
11183
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011184sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011185{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011186 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011187 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011188 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
11189 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011190 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011191 return () if(not $TypeInfo{$LibVersion}{$TypeId});
11192 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011193 return () if(not $Type{"Type"});
11194 if($Type{"Type"} ne $Type_Type)
11195 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011196 return () if(not defined $Type{"BaseType"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011197 return () if(not $Type{"BaseType"}{"Tid"});
11198 %Type = goToFirst($Type{"BaseType"}{"Tid"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011199 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011200 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011201 return %Type;
11202}
11203
11204my %TypeSpecAttributes = (
11205 "Const" => 1,
11206 "Volatile" => 1,
11207 "ConstVolatile" => 1,
11208 "Restrict" => 1,
11209 "Typedef" => 1
11210);
11211
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011212sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011213{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011214 my ($TypeId, $Info) = @_;
11215 if(not $TypeId or not $Info
11216 or not $Info->{$TypeId}) {
11217 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011218 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011219 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
11220 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
11221 }
11222 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011223 return %Type if(not defined $Type{"BaseType"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011224 return %Type if(not $Type{"BaseType"}{"Tid"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011225 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011226 %Type = get_PureType($Type{"BaseType"}{"Tid"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011227 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011228 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011229 return %Type;
11230}
11231
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011232sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011233{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011234 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011235 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011236 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
11237 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011238 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011239 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
11240 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011241 return 1 if($Type{"Type"}=~/FuncPtr|MethodPtr|FieldPtr/);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011242 return 0 if(not defined $Type{"BaseType"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011243 return 0 if(not $Type{"BaseType"}{"Tid"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011244 my $PointerLevel = 0;
11245 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|MethodPtr|FieldPtr/) {
11246 $PointerLevel += 1;
11247 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011248 $PointerLevel += get_PLevel($Type{"BaseType"}{"Tid"}, $LibVersion);
11249 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PointerLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011250 return $PointerLevel;
11251}
11252
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011253sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011254{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011255 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011256 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011257 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
11258 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011259 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011260 return () if(not $TypeInfo{$LibVersion}{$TypeId});
11261 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011262 return %Type if(not defined $Type{"BaseType"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011263 return %Type if(not $Type{"BaseType"}{"Tid"});
11264 %Type = get_BaseType($Type{"BaseType"}{"Tid"}, $LibVersion);
11265 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011266 return %Type;
11267}
11268
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011269sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011270{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011271 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011272 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011273 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
11274 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011275 return "" if(not defined $Type{"BaseType"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011276 return "" if(not $Type{"BaseType"}{"Tid"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011277 my $Qual = "";
11278 if($Type{"Type"} eq "Pointer") {
11279 $Qual .= "*";
11280 }
11281 elsif($Type{"Type"} eq "Ref") {
11282 $Qual .= "&";
11283 }
11284 elsif($Type{"Type"} eq "ConstVolatile") {
11285 $Qual .= "const volatile";
11286 }
11287 elsif($Type{"Type"} eq "Const"
11288 or $Type{"Type"} eq "Volatile"
11289 or $Type{"Type"} eq "Restrict") {
11290 $Qual .= lc($Type{"Type"});
11291 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011292 my $BQual = get_BaseTypeQual($Type{"BaseType"}{"Tid"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011293 return $BQual.$Qual;
11294}
11295
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011296sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011297{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011298 my ($TypeId, $Info) = @_;
11299 if(not $TypeId or not $Info
11300 or not $Info->{$TypeId}) {
11301 return ();
11302 }
11303 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011304 return %Type if(not defined $Type{"BaseType"});
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011305 if(my $BTid = $Type{"BaseType"}{"Tid"})
11306 {
11307 if($Info->{$BTid}) {
11308 return %{$Info->{$BTid}};
11309 }
11310 else { # something is going wrong
11311 return ();
11312 }
11313 }
11314 else {
11315 return %Type;
11316 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011317}
11318
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011319sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011320{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011321 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011322 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011323 return () if(not $TypeInfo{$LibVersion}{$TypeId});
11324 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011325}
11326
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040011327sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011328{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011329 my $Symbol = $_[0];
11330 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
11331}
11332
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011333sub isInLineInst($$$) {
11334 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
11335}
11336
11337sub isTemplateInstance($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011338{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011339 my ($Symbol, $SInfo, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011340 if($CheckObjectsOnly)
11341 {
11342 if($Symbol!~/\A(_Z|\?)/) {
11343 return 0;
11344 }
11345 if(my $Signature = $tr_name{$Symbol})
11346 {
11347 if(index($Signature,">")==-1) {
11348 return 0;
11349 }
11350 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
11351 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011352 if(index($ShortName,"<")!=-1
11353 and index($ShortName,">")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011354 return 1;
11355 }
11356 }
11357 }
11358 }
11359 else
11360 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011361 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011362 {
11363 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
11364 {
11365 if(index($ClassName,"<")!=-1) {
11366 return 1;
11367 }
11368 }
11369 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011370 if(my $ShortName = $SInfo->{"ShortName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011371 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011372 if(index($ShortName,"<")!=-1
11373 and index($ShortName,">")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011374 return 1;
11375 }
11376 }
11377 }
11378 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011379}
11380
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011381sub isTemplateSpec($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011382{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011383 my ($Symbol, $SInfo, $LibVersion) = @_;
11384 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011385 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011386 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011387 { # class specialization
11388 return 1;
11389 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011390 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011391 { # method specialization
11392 return 1;
11393 }
11394 }
11395 return 0;
11396}
11397
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011398sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011399{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011400 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040011401 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011402 { # non-public global data
11403 return 0;
11404 }
11405 if($CheckObjectsOnly) {
11406 return 0 if($Symbol=~/\A(_init|_fini)\Z/);
11407 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011408 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011409 { # support for old ABI dumps in --headers-only mode
11410 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
11411 {
11412 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
11413 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011414 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011415 if(not $PType or $PType eq "Unknown") {
11416 return 0;
11417 }
11418 }
11419 }
11420 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011421 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011422 {
11423 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011424 if($SkipSymbols{$LibVersion}{$Symbol})
11425 { # user defined symbols to ignore
11426 return 0;
11427 }
11428 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
11429 if(not $NameSpace and $ClassId)
11430 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011431 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011432 }
11433 if($NameSpace)
11434 { # user defined namespaces to ignore
11435 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
11436 return 0;
11437 }
11438 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
11439 { # nested namespaces
11440 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
11441 return 0;
11442 }
11443 }
11444 }
11445 if(my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
11446 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011447 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011448 { # --skip-headers or <skip_headers> (not <skip_including>)
11449 if($Skip==1) {
11450 return 0;
11451 }
11452 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011453 }
11454 if($SymbolsListPath and not $SymbolsList{$Symbol})
11455 { # user defined symbols
11456 return 0;
11457 }
11458 if($AppPath and not $SymbolsList_App{$Symbol})
11459 { # user defined symbols (in application)
11460 return 0;
11461 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011462 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
11463 { # non-target symbols
11464 return 0;
11465 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011466 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011467 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011468 if($CheckObjectsOnly)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011469 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011470 if(isTemplateInstance($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011471 return 0;
11472 }
11473 }
11474 else
11475 {
11476 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011477 or isInLineInst($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011478 {
11479 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
11480 { # inline virtual methods
11481 if($Type=~/InlineVirt/) {
11482 return 1;
11483 }
11484 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
11485 if(not $Allocable)
11486 { # check bases
11487 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
11488 {
11489 if(not isCopyingClass($DCId, $LibVersion))
11490 { # exists a derived class without default c-tor
11491 $Allocable=1;
11492 last;
11493 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011494 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011495 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011496 if(not $Allocable) {
11497 return 0;
11498 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011499 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011500 else
11501 { # inline non-virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011502 return 0;
11503 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011504 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011505 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011506 }
11507 }
11508 return 1;
11509}
11510
11511sub mergeImpl()
11512{
11513 my $DiffCmd = get_CmdPath("diff");
11514 if(not $DiffCmd) {
11515 exitStatus("Not_Found", "can't find \"diff\"");
11516 }
11517 foreach my $Interface (sort keys(%{$Symbol_Library{1}}))
11518 { # implementation changes
11519 next if($CompleteSignature{1}{$Interface}{"Private"});
11520 next if(not $CompleteSignature{1}{$Interface}{"Header"} and not $CheckObjectsOnly);
11521 next if(not $Symbol_Library{2}{$Interface} and not $Symbol_Library{2}{$SymVer{2}{$Interface}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011522 if(not symbolFilter($Interface, 1, "Affected", "Binary")) {
11523 next;
11524 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011525 my $Impl1 = canonifyImpl($Interface_Impl{1}{$Interface});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011526 next if(not $Impl1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011527 my $Impl2 = canonifyImpl($Interface_Impl{2}{$Interface});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011528 next if(not $Impl2);
11529 if($Impl1 ne $Impl2)
11530 {
11531 writeFile("$TMP_DIR/impl1", $Impl1);
11532 writeFile("$TMP_DIR/impl2", $Impl2);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040011533 my $Diff = `$DiffCmd -rNau \"$TMP_DIR/impl1\" \"$TMP_DIR/impl2\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011534 $Diff=~s/(---|\+\+\+).+\n//g;
11535 $Diff=~s/[ ]{3,}/ /g;
11536 $Diff=~s/\n\@\@/\n \n\@\@/g;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040011537 unlink("$TMP_DIR/impl1");
11538 unlink("$TMP_DIR/impl2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011539 %{$ImplProblems{$Interface}}=(
11540 "Diff" => get_CodeView($Diff) );
11541 }
11542 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011543
11544 # clean memory
11545 %Interface_Impl = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011546}
11547
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011548sub canonifyImpl($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011549{
11550 my $FuncBody= $_[0];
11551 return "" if(not $FuncBody);
11552 $FuncBody=~s/0x[a-f\d]+/0x?/g;# addr
11553 $FuncBody=~s/((\A|\n)[a-z]+[\t ]+)[a-f\d]+([^x]|\Z)/$1?$3/g;# call, jump
11554 $FuncBody=~s/# [a-f\d]+ /# ? /g;# call, jump
11555 $FuncBody=~s/%([a-z]+[a-f\d]*)/\%reg/g;# registers
11556 while($FuncBody=~s/\nnop[ \t]*(\n|\Z)/$1/g){};# empty op
11557 $FuncBody=~s/<.+?\.cpp.+?>/<name.cpp>/g;
11558 $FuncBody=~s/(\A|\n)[a-f\d]+ </$1? </g;# 5e74 <_ZN...
11559 $FuncBody=~s/\.L\d+/.L/g;
11560 $FuncBody=~s/#(-?)\d+/#$1?/g;# r3, [r3, #120]
11561 $FuncBody=~s/[\n]{2,}/\n/g;
11562 return $FuncBody;
11563}
11564
11565sub get_CodeView($)
11566{
11567 my $Code = $_[0];
11568 my $View = "";
11569 foreach my $Line (split(/\n/, $Code))
11570 {
11571 if($Line=~s/\A(\+|-)/$1 /g)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011572 { # bold line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011573 $View .= "<tr><td><b>".htmlSpecChars($Line)."</b></td></tr>\n";
11574 }
11575 else {
11576 $View .= "<tr><td>".htmlSpecChars($Line)."</td></tr>\n";
11577 }
11578 }
11579 return "<table class='code_view'>$View</table>\n";
11580}
11581
11582sub getImplementations($$)
11583{
11584 my ($LibVersion, $Path) = @_;
11585 return if(not $LibVersion or not -e $Path);
11586 if($OSgroup eq "macos")
11587 {
11588 my $OtoolCmd = get_CmdPath("otool");
11589 if(not $OtoolCmd) {
11590 exitStatus("Not_Found", "can't find \"otool\"");
11591 }
11592 my $CurInterface = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040011593 foreach my $Line (split(/\n/, `$OtoolCmd -tv \"$Path\" 2>\"$TMP_DIR/null\"`))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011594 {
11595 if($Line=~/\A\s*_(\w+)\s*:/i) {
11596 $CurInterface = $1;
11597 }
11598 elsif($Line=~/\A\s*[\da-z]+\s+(.+?)\Z/i) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011599 $Interface_Impl{$LibVersion}{$CurInterface} .= $1."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011600 }
11601 }
11602 }
11603 else
11604 {
11605 my $ObjdumpCmd = get_CmdPath("objdump");
11606 if(not $ObjdumpCmd) {
11607 exitStatus("Not_Found", "can't find \"objdump\"");
11608 }
11609 my $CurInterface = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040011610 foreach my $Line (split(/\n/, `$ObjdumpCmd -d \"$Path\" 2>\"$TMP_DIR/null\"`))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011611 {
11612 if($Line=~/\A[\da-z]+\s+<(\w+)>/i) {
11613 $CurInterface = $1;
11614 }
11615 else
11616 { # x86: 51fa:(\t)89 e5 (\t)mov %esp,%ebp
11617 # arm: 5020:(\t)e24cb004(\t)sub(\t)fp, ip, #4(\t); 0x4
11618 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 +040011619 $Interface_Impl{$LibVersion}{$CurInterface} .= $2."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011620 }
11621 }
11622 }
11623 }
11624}
11625
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011626sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011627{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011628 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011629 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
11630 {
11631 if(link_symbol($Symbol, 1, "+Deps"))
11632 { # linker can find a new symbol
11633 # in the old-version library
11634 # So, it's not a new symbol
11635 next;
11636 }
11637 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011638 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011639 next;
11640 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011641 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011642 }
11643}
11644
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011645sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011646{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011647 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011648 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
11649 {
11650 if($CheckObjectsOnly) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011651 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011652 }
11653 if(link_symbol($Symbol, 2, "+Deps"))
11654 { # linker can find an old symbol
11655 # in the new-version library
11656 next;
11657 }
11658 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011659 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011660 next;
11661 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011662 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011663 }
11664}
11665
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011666sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011667{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011668 my $Level = $_[0];
11669 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011670 { # checking added symbols
11671 next if($CompleteSignature{2}{$Symbol}{"Private"});
11672 next if(not $CompleteSignature{2}{$Symbol}{"Header"} and not $CheckObjectsOnly);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011673 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011674 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011675 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011676 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011677 { # checking removed symbols
11678 next if($CompleteSignature{1}{$Symbol}{"Private"});
11679 next if(not $CompleteSignature{1}{$Symbol}{"Header"} and not $CheckObjectsOnly);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011680 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011681 { # skip v-tables for templates, that should not be imported by applications
11682 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011683 if(my $CName = $VTableClass{$Symbol})
11684 {
11685 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
11686 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011687 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011688 next;
11689 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011690 }
11691 }
11692 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011693 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011694 }
11695 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
11696 { # symbols for pure virtual methods cannot be called by clients
11697 next;
11698 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011699 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011700 }
11701}
11702
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011703sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011704{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011705 my ($LibVersion, $V) = @_;
11706 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
11707 return $Cache{"checkDump"}{$LibVersion}{$V};
11708 }
11709 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011710}
11711
11712sub detectAdded_H($)
11713{
11714 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011715 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
11716 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011717 if($Level eq "Source")
11718 { # remove symbol version
11719 my ($SN, $SS, $SV) = separate_symbol($Symbol);
11720 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040011721
11722 if($CompleteSignature{2}{$Symbol}{"Artificial"})
11723 { # skip artificial constructors
11724 next;
11725 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011726 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011727 if(not $CompleteSignature{2}{$Symbol}{"Header"}
11728 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011729 next;
11730 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011731 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011732 next;
11733 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011734 if(not defined $CompleteSignature{1}{$Symbol}
11735 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
11736 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011737 if($UsedDump{2}{"SrcBin"})
11738 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011739 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011740 { # support for old and different (!) ABI dumps
11741 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
11742 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011743 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011744 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011745 {
11746 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
11747 {
11748 if($Lang eq "C")
11749 { # support for old ABI dumps: missed extern "C" functions
11750 next;
11751 }
11752 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011753 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011754 else
11755 {
11756 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011757 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011758 next;
11759 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011760 }
11761 }
11762 }
11763 }
11764 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011765 }
11766 }
11767}
11768
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011769sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011770{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011771 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011772 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
11773 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011774 if($Level eq "Source")
11775 { # remove symbol version
11776 my ($SN, $SS, $SV) = separate_symbol($Symbol);
11777 $Symbol=$SN;
11778 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011779 if(not $CompleteSignature{1}{$Symbol}{"Header"}
11780 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011781 next;
11782 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011783 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011784 next;
11785 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011786 if(not defined $CompleteSignature{2}{$Symbol}
11787 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011788 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011789 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011790 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011791 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011792 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011793 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
11794 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011795 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011796 if($CheckHeadersOnly)
11797 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011798 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
11799 {
11800 if($Lang eq "C")
11801 { # support for old ABI dumps: missed extern "C" functions
11802 next;
11803 }
11804 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011805 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011806 else
11807 {
11808 if(not link_symbol($Symbol, 1, "-Deps"))
11809 { # skip removed inline symbols
11810 next;
11811 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011812 }
11813 }
11814 }
11815 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040011816 if(not checkDump(1, "2.15"))
11817 {
11818 if($Symbol=~/_IT_E\Z/)
11819 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
11820 next;
11821 }
11822 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011823 if(not $CompleteSignature{1}{$Symbol}{"Class"})
11824 {
11825 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
11826 {
11827 if(defined $Constants{2}{$Short})
11828 {
11829 my $Val = $Constants{2}{$Short}{"Value"};
11830 if(defined $Func_ShortName{2}{$Val})
11831 { # old name defined to new
11832 next;
11833 }
11834 }
11835 }
11836
11837 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011838 $RemovedInt{$Level}{$Symbol} = 1;
11839 if($Level eq "Source")
11840 { # search for a source-compatible equivalent
11841 setAlternative($Symbol, $Level);
11842 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011843 }
11844 }
11845}
11846
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011847sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011848{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011849 my $Level = $_[0];
11850 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011851 { # checking added symbols
11852 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011853 next if($CompleteSignature{2}{$Symbol}{"Private"});
11854 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011855 if($Level eq "Binary")
11856 {
11857 if($CompleteSignature{2}{$Symbol}{"InLine"})
11858 {
11859 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
11860 { # skip inline non-virtual functions
11861 next;
11862 }
11863 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011864 }
11865 else
11866 { # Source
11867 if($SourceAlternative_B{$Symbol}) {
11868 next;
11869 }
11870 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011871 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011872 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011873 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011874 { # checking removed symbols
11875 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011876 next if($CompleteSignature{1}{$Symbol}{"Private"});
11877 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011878 if($Level eq "Binary")
11879 {
11880 if($CompleteSignature{1}{$Symbol}{"InLine"})
11881 {
11882 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
11883 { # skip inline non-virtual functions
11884 next;
11885 }
11886 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011887 }
11888 else
11889 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011890 if(my $Alt = $SourceAlternative{$Symbol})
11891 {
11892 if(defined $CompleteSignature{1}{$Alt}
11893 and $CompleteSignature{1}{$Symbol}{"Const"})
11894 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011895 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011896 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011897 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011898 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011899 }
11900 else
11901 { # do NOT show removed symbol
11902 next;
11903 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011904 }
11905 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011906 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011907 }
11908}
11909
11910sub addParamNames($)
11911{
11912 my $LibraryVersion = $_[0];
11913 return if(not keys(%AddIntParams));
11914 my $SecondVersion = $LibraryVersion==1?2:1;
11915 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
11916 {
11917 next if(not keys(%{$AddIntParams{$Interface}}));
11918 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011919 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011920 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
11921 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011922 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011923 if(defined $CompleteSignature{$SecondVersion}{$Interface}
11924 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
11925 {
11926 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
11927 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
11928 }
11929 }
11930 else {
11931 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
11932 }
11933 }
11934 }
11935 }
11936}
11937
11938sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040011939{ # detect changed typedefs to show
11940 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011941 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
11942 {
11943 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040011944 my $BName1 = $Typedef_BaseName{1}{$Typedef};
11945 if(not $BName1 or isAnon($BName1)) {
11946 next;
11947 }
11948 my $BName2 = $Typedef_BaseName{2}{$Typedef};
11949 if(not $BName2 or isAnon($BName2)) {
11950 next;
11951 }
11952 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011953 $ChangedTypedef{$Typedef} = 1;
11954 }
11955 }
11956}
11957
11958sub get_symbol_suffix($$)
11959{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011960 my ($Symbol, $Full) = @_;
11961 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040011962 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011963 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011964 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011965 if(not $Full) {
11966 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
11967 }
11968 return $Suffix;
11969}
11970
11971sub get_symbol_prefix($$)
11972{
11973 my ($Symbol, $LibVersion) = @_;
11974 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
11975 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
11976 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011977 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011978 }
11979 return $ShortName;
11980}
11981
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011982sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011983{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011984 my $Symbol = $_[0];
11985 my $PSymbol = $Symbol;
11986 if(not defined $CompleteSignature{2}{$PSymbol}
11987 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
11988 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
11989 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011990 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011991 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011992 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011993 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011994 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
11995 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011996 {
11997 if(defined $CompleteSignature{2}{$PSymbol}
11998 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
11999 {
12000 $SourceAlternative{$Symbol} = $PSymbol;
12001 $SourceAlternative_B{$PSymbol} = $Symbol;
12002 if(not defined $CompleteSignature{1}{$PSymbol}
12003 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
12004 $SourceReplacement{$Symbol} = $PSymbol;
12005 }
12006 }
12007 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012008 }
12009 else
12010 {
12011 foreach my $Sp ("KV", "VK", "K", "V")
12012 {
12013 if($PSymbol=~s/\A_ZN$Sp/_ZN/
12014 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
12015 {
12016 if(defined $CompleteSignature{2}{$PSymbol}
12017 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
12018 {
12019 $SourceAlternative{$Symbol} = $PSymbol;
12020 $SourceAlternative_B{$PSymbol} = $Symbol;
12021 if(not defined $CompleteSignature{1}{$PSymbol}
12022 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
12023 $SourceReplacement{$Symbol} = $PSymbol;
12024 }
12025 }
12026 }
12027 $PSymbol = $Symbol;
12028 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012029 }
12030 }
12031 }
12032 return "";
12033}
12034
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012035sub getSymKind($$)
12036{
12037 my ($Symbol, $LibVersion) = @_;
12038 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
12039 {
12040 return "Global_Data";
12041 }
12042 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
12043 {
12044 return "Method";
12045 }
12046 return "Function";
12047}
12048
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012049sub mergeSignatures($)
12050{
12051 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012052 my %SubProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012053
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012054 mergeBases($Level);
12055
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012056 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012057 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012058 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012059 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012060 next;
12061 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012062 if(defined $CompleteSignature{1}{$Symbol}
12063 and $CompleteSignature{1}{$Symbol}{"Header"})
12064 { # double-check added symbol
12065 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012066 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012067 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012068 next;
12069 }
12070 if($Symbol=~/\A(_Z|\?)/)
12071 { # C++
12072 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
12073 }
12074 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
12075 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012076 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
12077 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012078 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012079 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012080 {
12081 if($TName_Tid{1}{$AffectedClass_Name})
12082 { # class should exist in previous version
12083 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
12084 { # old v-table is NOT copied by old applications
12085 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
12086 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012087 "Target"=>get_Signature($Symbol, 2),
12088 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012089 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012090 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012091 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012092 }
12093 }
12094 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012095 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
12096 { # check all removed exported symbols
12097 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012098 next;
12099 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012100 if(defined $CompleteSignature{2}{$Symbol}
12101 and $CompleteSignature{2}{$Symbol}{"Header"})
12102 { # double-check removed symbol
12103 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012104 }
12105 if($CompleteSignature{1}{$Symbol}{"Private"})
12106 { # skip private methods
12107 next;
12108 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012109 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012110 next;
12111 }
12112 $CheckedSymbols{$Level}{$Symbol} = 1;
12113 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
12114 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012115 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
12116 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012117 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012118 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
12119 {
12120 if($TName_Tid{2}{$AffectedClass_Name})
12121 { # class should exist in newer version
12122 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
12123 { # old v-table is NOT copied by old applications
12124 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
12125 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012126 "Target"=>get_Signature($OverriddenMethod, 1),
12127 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012128 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012129 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012130 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012131 }
12132 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012133 if($Level eq "Binary"
12134 and $OSgroup eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012135 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012136 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012137 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012138 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012139 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012140 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012141 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012142 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012143 {
12144 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
12145 "Target"=>$tr_name{$Symbol},
12146 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012147 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012148 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012149 else
12150 {
12151 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_NonStatic"}{$tr_name{$Symbol}}}=(
12152 "Target"=>$tr_name{$Symbol},
12153 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012154 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012155 }
12156 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012157 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012158 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012159 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012160 {
12161 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
12162 "Target"=>$tr_name{$Symbol},
12163 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012164 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012165 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012166 else
12167 {
12168 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_NonVirtual"}{$tr_name{$Symbol}}}=(
12169 "Target"=>$tr_name{$Symbol},
12170 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012171 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012172 }
12173 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012174 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
12175 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
12176 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
12177 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
12178 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012179 {
12180 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012181 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012182 $ProblemType = "Global_Data_Symbol_Changed_Type";
12183 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012184 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
12185 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012186 "Old_Type"=>$RTName1,
12187 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012188 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012189 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012190 }
12191 }
12192 }
12193 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012194 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012195 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012196 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012197 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012198 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012199 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012200 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012201 if($CompleteSignature{1}{$Symbol}{"Constructor"})
12202 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012203 if($Symbol=~/(C1E|C2E)/)
12204 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012205 my $CtorType = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012206 $NewSym=~s/(C1E|C2E)/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012207 }
12208 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012209 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
12210 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012211 if($Symbol=~/(D0E|D1E|D2E)/)
12212 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012213 my $DtorType = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012214 $NewSym=~s/(D0E|D1E|D2E)/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012215 }
12216 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012217 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012218 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012219 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012220 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012221 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012222 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012223 { # "const" to non-"const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012224 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_NonConst"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012225 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012226 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012227 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012228 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012229 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012230 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012231 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012232 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012233 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012234 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012235 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012236 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012237 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012238 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012239 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012240 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012241 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012242 { # "volatile" to non-"volatile"
12243
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012244 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_NonVolatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012245 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012246 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012247 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012248 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012249 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012250 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012251 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012252 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012253 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012254 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012255 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012256 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012257 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012258 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012259 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012260 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012261 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
12262 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012263 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012264 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012265 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012266 }
12267 }
12268 }
12269 }
12270 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012271 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12272 { # checking symbols
12273 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12274 if($Level eq "Source")
12275 { # remove symbol version
12276 $Symbol=$SN;
12277 }
12278 else
12279 { # Binary
12280 if(not $SV)
12281 { # symbol without version
12282 if(my $VSym = $SymVer{1}{$Symbol})
12283 { # the symbol is linked with versioned symbol
12284 if($CompleteSignature{2}{$VSym}{"MnglName"})
12285 { # show report for symbol@ver only
12286 next;
12287 }
12288 elsif(not link_symbol($VSym, 2, "-Deps"))
12289 { # changed version: sym@v1 to sym@v2
12290 # do NOT show report for symbol
12291 next;
12292 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012293 }
12294 }
12295 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012296 my $PSymbol = $Symbol;
12297 if($Level eq "Source"
12298 and my $S = $SourceReplacement{$Symbol})
12299 { # take a source-compatible replacement function
12300 $PSymbol = $S;
12301 }
12302 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012303 { # private symbols
12304 next;
12305 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012306 if(not defined $CompleteSignature{1}{$Symbol}
12307 or not defined $CompleteSignature{2}{$PSymbol})
12308 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012309 next;
12310 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012311 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
12312 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
12313 { # no mangled name
12314 next;
12315 }
12316 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12317 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012318 { # without a header
12319 next;
12320 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012321
12322 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
12323 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
12324 { # became pure
12325 next;
12326 }
12327 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
12328 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
12329 { # became non-pure
12330 next;
12331 }
12332
12333 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
12334 { # exported, target, inline virtual and pure virtual
12335 next;
12336 }
12337 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
12338 { # exported, target, inline virtual and pure virtual
12339 next;
12340 }
12341
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012342 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012343 {
12344 if($CompleteSignature{1}{$Symbol}{"Data"}
12345 and $CompleteSignature{2}{$PSymbol}{"Data"})
12346 {
12347 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
12348 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
12349 if(defined $Value1)
12350 {
12351 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
12352 if(defined $Value2)
12353 {
12354 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
12355 if($Value1 ne $Value2)
12356 {
12357 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
12358 "Old_Value"=>$Value1,
12359 "New_Value"=>$Value2,
12360 "Target"=>get_Signature($Symbol, 1) );
12361 }
12362 }
12363 }
12364 }
12365 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012366
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012367 if($CompleteSignature{2}{$PSymbol}{"Private"})
12368 {
12369 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
12370 "Target"=>get_Signature_M($PSymbol, 2) );
12371 }
12372 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
12373 and $CompleteSignature{2}{$PSymbol}{"Protected"})
12374 {
12375 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
12376 "Target"=>get_Signature_M($PSymbol, 2) );
12377 }
12378 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
12379 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
12380 {
12381 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
12382 "Target"=>get_Signature_M($PSymbol, 2) );
12383 }
12384
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012385 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012386 mergeVirtualTables($Symbol, $Level);
12387
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012388 if($COMPILE_ERRORS)
12389 { # if some errors occurred at the compiling stage
12390 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012391 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012392 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012393 { # missed information about parameters in newer version
12394 next;
12395 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012396 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012397 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012398 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012399 next;
12400 }
12401 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012402 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012403 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012404 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012405 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
12406 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012407 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
12408 "Target"=>get_Signature($Symbol, 1)
12409 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012410 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012411 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012412 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
12413 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012414 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_NonStatic"}{""}}=(
12415 "Target"=>get_Signature($Symbol, 1)
12416 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012417 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012418 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
12419 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012420 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012421 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012422 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012423 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
12424 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
12425 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012426 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012427 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012428 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
12429 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012430 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012431 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012432 my $ProblemType = "Virtual_Method_Position";
12433 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
12434 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012435 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012436 if(isUsedClass($Class_Id, 1, $Level))
12437 {
12438 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012439 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012440 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012441 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
12442 next;
12443 }
12444 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012445 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012446 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
12447 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012448 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012449 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012450 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012451 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012452 }
12453 }
12454 }
12455 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012456 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
12457 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012458 { # do NOT check type changes in pure virtuals
12459 next;
12460 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012461 $CheckedSymbols{$Level}{$Symbol}=1;
12462 if($Symbol=~/\A(_Z|\?)/
12463 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012464 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012465 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012466 { # checking parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012467 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012468 }
12469 }
12470 else
12471 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012472 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012473 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012474 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012475 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
12476 last if($PType2_Name eq "...");
12477 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
12478 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012479 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012480 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012481 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012482 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
12483 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012484 if($#Positions1==-1 or $#Positions2>$#Positions1) {
12485 $ParamPos_Prev = "lost";
12486 }
12487 }
12488 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012489 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012490 }
12491 if($ParamPos_Prev eq "lost")
12492 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012493 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012494 {
12495 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012496 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012497 $ProblemType = "Added_Unnamed_Parameter";
12498 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012499 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012500 "Target"=>$PName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012501 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012502 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012503 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012504 }
12505 else
12506 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012507 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012508 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012509 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012510 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
12511 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012512 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012513 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012514 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012515 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012516 "Target"=>$PName_Old,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012517 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012518 "Param_Type"=>$PType2_Name,
12519 "Old_Value"=>$PName_Old,
12520 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012521 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012522 }
12523 }
12524 else
12525 {
12526 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012527 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012528 $ProblemType = "Added_Middle_Unnamed_Parameter";
12529 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012530 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012531 "Target"=>$PName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012532 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012533 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012534 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012535 }
12536 }
12537 }
12538 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012539 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012540 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012541 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012542 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012543 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012544 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012545 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012546 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012547 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012548 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
12549 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012550 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012551 }
12552 }
12553 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012554 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012555 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012556 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012557 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
12558 last if($PType1_Name eq "...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012559 my $Parameter_Name = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
12560 my $Parameter_NewName = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012561 my $ParamPos_New = "-1";
12562 if($Parameter_Name=~/\Ap\d+\Z/i)
12563 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012564 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
12565 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012566 if($#Positions2==-1 or $#Positions2<$#Positions1) {
12567 $ParamPos_New = "lost";
12568 }
12569 }
12570 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012571 $ParamPos_New = find_ParamPair_Pos_byName($Parameter_Name, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012572 }
12573 if($ParamPos_New eq "lost")
12574 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012575 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012576 {
12577 my $ProblemType = "Removed_Parameter";
12578 if($Parameter_Name=~/\Ap\d+\Z/) {
12579 $ProblemType = "Removed_Unnamed_Parameter";
12580 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012581 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012582 "Target"=>$Parameter_Name,
12583 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012584 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012585 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012586 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012587 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012588 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012589 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012590 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012591 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012592 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012593 and find_ParamPair_Pos_byName($Parameter_NewName, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012594 {
12595 if($Parameter_NewName!~/\Ap\d+\Z/ and $Parameter_Name!~/\Ap\d+\Z/)
12596 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012597 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012598 "Target"=>$Parameter_Name,
12599 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012600 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012601 "Old_Value"=>$Parameter_Name,
12602 "New_Value"=>$Parameter_NewName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012603 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012604 }
12605 }
12606 else
12607 {
12608 my $ProblemType = "Removed_Middle_Parameter";
12609 if($Parameter_Name=~/\Ap\d+\Z/) {
12610 $ProblemType = "Removed_Middle_Unnamed_Parameter";
12611 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012612 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012613 "Target"=>$Parameter_Name,
12614 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012615 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012616 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012617 }
12618 }
12619 }
12620 }
12621 }
12622 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012623 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
12624 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
12625 %SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012626 foreach my $SubProblemType (keys(%SubProblems))
12627 {
12628 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
12629 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
12630 my $NewProblemType = $SubProblemType;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012631 my $AddProblemType = undef;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012632
12633 if($SubProblemType eq "Return_Type_And_Size"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012634 and $CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012635 $NewProblemType = "Global_Data_Type_And_Size";
12636 }
12637 elsif($SubProblemType eq "Return_Type")
12638 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012639 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012640 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012641 if(removedQual($Old_Value, $New_Value, "const"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012642 { # const -> non-const global data
12643 $NewProblemType = "Global_Data_Became_Non_Const";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012644 $AddProblemType = "Global_Data_Type";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012645 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012646 elsif(addedQual($Old_Value, $New_Value, "const"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012647 { # non-const -> const global data
12648 $NewProblemType = "Global_Data_Became_Const";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012649 $AddProblemType = "Global_Data_Type";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012650 }
12651 else {
12652 $NewProblemType = "Global_Data_Type";
12653 }
12654 }
12655 else
12656 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012657 if(addedQual($Old_Value, $New_Value, "const"))
12658 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012659 $NewProblemType = "Return_Type_Became_Const";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012660 $AddProblemType = "Return_Type";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012661 }
12662 }
12663 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012664 elsif($SubProblemType eq "Return_Type_Format")
12665 {
12666 if($CompleteSignature{1}{$Symbol}{"Data"}) {
12667 $NewProblemType = "Global_Data_Type_Format";
12668 }
12669 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012670 if($Level eq "Binary"
12671 and not $CompleteSignature{1}{$Symbol}{"Data"})
12672 {
12673 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
12674 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
12675 { # if one of the architectures is unknown
12676 # then set other arhitecture to unknown too
12677 ($Arch1, $Arch2) = ("unknown", "unknown");
12678 }
12679 my (%Conv1, %Conv2) = ();
12680 if($UseConv_Real{1} and $UseConv_Real{1})
12681 {
12682 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
12683 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
12684 }
12685 else
12686 {
12687 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
12688 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
12689 }
12690
12691 if($SubProblemType eq "Return_Type_Became_Void")
12692 {
12693 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
12694 { # parameters stack has been affected
12695 if($Conv1{"Method"} eq "stack") {
12696 $NewProblemType = "Return_Type_Became_Void_And_Stack_Layout";
12697 }
12698 elsif($Conv1{"Hidden"}) {
12699 $NewProblemType = "Return_Type_Became_Void_And_Register";
12700 }
12701 }
12702 }
12703 elsif($SubProblemType eq "Return_Type_From_Void")
12704 {
12705 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
12706 { # parameters stack has been affected
12707 if($Conv2{"Method"} eq "stack") {
12708 $NewProblemType = "Return_Type_From_Void_And_Stack_Layout";
12709 }
12710 elsif($Conv2{"Hidden"}) {
12711 $NewProblemType = "Return_Type_From_Void_And_Register";
12712 }
12713 }
12714 }
12715 elsif($SubProblemType eq "Return_Type"
12716 or $SubProblemType eq "Return_Type_And_Size"
12717 or $SubProblemType eq "Return_Type_Format")
12718 {
12719 if($Conv1{"Method"} ne $Conv2{"Method"})
12720 {
12721 if($Conv1{"Method"} eq "stack")
12722 { # returns in a register instead of a hidden first parameter
12723 $NewProblemType = "Return_Type_From_Stack_To_Register";
12724 }
12725 else {
12726 $NewProblemType = "Return_Type_From_Register_To_Stack";
12727 }
12728 }
12729 else
12730 {
12731 if($Conv1{"Method"} eq "reg")
12732 {
12733 if($Conv1{"Registers"} ne $Conv2{"Registers"})
12734 {
12735 if($Conv1{"Hidden"}) {
12736 $NewProblemType = "Return_Type_And_Register_Was_Hidden_Parameter";
12737 }
12738 elsif($Conv2{"Hidden"}) {
12739 $NewProblemType = "Return_Type_And_Register_Became_Hidden_Parameter";
12740 }
12741 else {
12742 $NewProblemType = "Return_Type_And_Register";
12743 }
12744 }
12745 }
12746 }
12747 }
12748 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012749 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{"retval"}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012750 if(defined $AddProblemType) {
12751 @{$CompatProblems{$Level}{$Symbol}{$AddProblemType}{"retval"}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
12752 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012753 }
12754 if($ReturnType1_Id and $ReturnType2_Id)
12755 {
12756 @RecurTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012757 %SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012758 foreach my $SubProblemType (keys(%SubProblems))
12759 { # add "Global_Data_Size" problem
12760 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
12761 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
12762 if($SubProblemType eq "DataType_Size"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012763 and $CompleteSignature{1}{$Symbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012764 and get_PLevel($ReturnType1_Id, 1)==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012765 { # add a new problem
12766 %{$SubProblems{"Global_Data_Size"}} = %{$SubProblems{$SubProblemType}};
12767 }
12768 }
12769 foreach my $SubProblemType (keys(%SubProblems))
12770 {
12771 foreach my $SubLocation (keys(%{$SubProblems{$SubProblemType}}))
12772 {
12773 my $NewLocation = ($SubLocation)?"retval->".$SubLocation:"retval";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012774 %{$CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012775 "Return_Type_Name"=>$TypeInfo{1}{$ReturnType1_Id}{"Name"} );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012776 @{$CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}}{keys(%{$SubProblems{$SubProblemType}{$SubLocation}})} = values %{$SubProblems{$SubProblemType}{$SubLocation}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012777 if($SubLocation!~/\-\>/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012778 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}{"Start_Type_Name"} = $TypeInfo{1}{$ReturnType1_Id}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012779 }
12780 }
12781 }
12782 }
12783
12784 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012785 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
12786 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
12787 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012788 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012789 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012790 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
12791 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012792 if($ThisPtr1_Id and $ThisPtr2_Id)
12793 {
12794 @RecurTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012795 %SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012796 foreach my $SubProblemType (keys(%SubProblems))
12797 {
12798 foreach my $SubLocation (keys(%{$SubProblems{$SubProblemType}}))
12799 {
12800 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012801 %{$CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012802 "Object_Type_Name"=>$TypeInfo{1}{$ObjTId1}{"Name"} );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012803 @{$CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}}{keys(%{$SubProblems{$SubProblemType}{$SubLocation}})} = values %{$SubProblems{$SubProblemType}{$SubLocation}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012804 if($SubLocation!~/\-\>/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012805 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}{"Start_Type_Name"} = $TypeInfo{1}{$ObjTId1}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012806 }
12807 }
12808 }
12809 }
12810 }
12811 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012812 if($Level eq "Binary") {
12813 mergeVTables($Level);
12814 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012815 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
12816 $CheckedSymbols{$Level}{$Symbol} = 1;
12817 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012818}
12819
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012820sub rmQuals($$)
12821{
12822 my ($Value, $Qual) = @_;
12823 if(not $Qual) {
12824 return $Value;
12825 }
12826 if($Qual eq "all")
12827 { # all quals
12828 $Qual = "const|volatile|restrict";
12829 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012830 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012831 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012832 }
12833 return $Value;
12834}
12835
12836sub cmpBTypes($$$$)
12837{
12838 my ($T1, $T2, $V1, $V2) = @_;
12839 $T1 = uncover_typedefs($T1, $V1);
12840 $T2 = uncover_typedefs($T2, $V2);
12841 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
12842}
12843
12844sub addedQual($$$)
12845{
12846 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012847 return removedQual_($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012848}
12849
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012850sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012851{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012852 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012853 return removedQual_($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012854}
12855
12856sub removedQual_($$$$$)
12857{
12858 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
12859 $Old_Value = uncover_typedefs($Old_Value, $V1);
12860 $New_Value = uncover_typedefs($New_Value, $V2);
12861 if($Old_Value eq $New_Value)
12862 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012863 return 0;
12864 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012865 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012866 { # without a qual
12867 return 0;
12868 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012869 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012870 { # became non-qual
12871 return 1;
12872 }
12873 else
12874 {
12875 my @BQ1 = getQualModel($Old_Value, $Qual);
12876 my @BQ2 = getQualModel($New_Value, $Qual);
12877 foreach (0 .. $#BQ1)
12878 { # removed qual
12879 if($BQ1[$_]==1
12880 and $BQ2[$_]!=1)
12881 {
12882 return 2;
12883 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012884 }
12885 }
12886 return 0;
12887}
12888
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012889sub getQualModel($$)
12890{
12891 my ($Value, $Qual) = @_;
12892 if(not $Qual) {
12893 return $Value;
12894 }
12895
12896 # cleaning
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012897 while($Value=~/(\w+)/ and $1 ne $Qual) {
12898 $Value=~s/\b$1\b//g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012899 }
12900 $Value=~s/[^\*\&\w]+//g;
12901
12902 # modeling
12903 # int*const*const == 011
12904 # int**const == 001
12905 my @Model = ();
12906 my @Elems = split(/[\*\&]/, $Value);
12907 if(not @Elems) {
12908 return (0);
12909 }
12910 foreach (@Elems)
12911 {
12912 if($_ eq $Qual) {
12913 push(@Model, 1);
12914 }
12915 else {
12916 push(@Model, 0);
12917 }
12918 }
12919
12920 return @Model;
12921}
12922
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040012923my %StringTypes = map {$_=>1} (
12924 "char*",
12925 "char const*"
12926);
12927
12928my %CharTypes = map {$_=>1} (
12929 "char",
12930 "char const"
12931);
12932
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012933sub showVal($$$)
12934{
12935 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012936 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040012937 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012938 if(substr($Value, 0, 2) eq "_Z")
12939 {
12940 if(my $Unmangled = $tr_name{$Value}) {
12941 return $Unmangled;
12942 }
12943 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040012944 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012945 { # strings
12946 return "\"$Value\"";
12947 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040012948 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012949 { # characters
12950 return "\'$Value\'";
12951 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040012952 if($Value eq "")
12953 { # other
12954 return "\'\'";
12955 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012956 return $Value;
12957}
12958
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012959sub mergeParameters($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012960{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012961 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012962 if(not $Symbol) {
12963 return;
12964 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012965 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
12966 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
12967 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
12968 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012969 if(not $PType1_Id
12970 or not $PType2_Id) {
12971 return;
12972 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012973 my %Type1 = get_Type($PType1_Id, 1);
12974 my %Type2 = get_Type($PType2_Id, 2);
12975 my %BaseType1 = get_BaseType($PType1_Id, 1);
12976 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012977 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012978 if($Level eq "Binary")
12979 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012980 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012981 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
12982 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
12983 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
12984 {
12985 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012986 "Target"=>$PName1,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012987 "Param_Pos"=>$ParamPos1 );
12988 }
12989 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
12990 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
12991 {
12992 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012993 "Target"=>$PName1,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012994 "Param_Pos"=>$ParamPos1 );
12995 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012996 }
12997 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012998 if(checkDump(1, "2.0") and checkDump(2, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012999 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013000 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
13001 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013002 if(not checkDump(1, "2.13")
13003 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013004 { # support for old ABI dumps
13005 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013006 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013007 if($Type1{"Name"} eq "bool"
13008 and $Value_Old eq "false" and $Value_New eq "0")
13009 { # int class::method ( bool p = 0 );
13010 # old ABI dumps: "false"
13011 # new ABI dumps: "0"
13012 $Value_Old = "0";
13013 }
13014 }
13015 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040013016 if(not checkDump(1, "2.18")
13017 and checkDump(2, "2.18"))
13018 { # support for old ABI dumps
13019 if(not defined $Value_Old
13020 and substr($Value_New, 0, 2) eq "_Z") {
13021 $Value_Old = $Value_New;
13022 }
13023 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013024 if(defined $Value_Old)
13025 {
13026 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
13027 if(defined $Value_New)
13028 {
13029 $Value_New = showVal($Value_New, $PType2_Id, 2);
13030 if($Value_Old ne $Value_New)
13031 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013032 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013033 "Target"=>$PName1,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013034 "Param_Pos"=>$ParamPos1,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013035 "Old_Value"=>$Value_Old,
13036 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013037 }
13038 }
13039 else
13040 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013041 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013042 "Target"=>$PName1,
13043 "Param_Pos"=>$ParamPos1,
13044 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013045 }
13046 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013047 elsif(defined $Value_New)
13048 {
13049 $Value_New = showVal($Value_New, $PType2_Id, 2);
13050 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
13051 "Target"=>$PName1,
13052 "Param_Pos"=>$ParamPos1,
13053 "New_Value"=>$Value_New );
13054 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013055 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013056 if($PName1 and $PName2 and $PName1 ne $PName2
13057 and $PType1_Id!=-1 and $PType2_Id!=-1
13058 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013059 { # except unnamed "..." value list (Id=-1)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013060 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013061 "Target"=>$PName1,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013062 "Param_Pos"=>$ParamPos1,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013063 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013064 "Old_Value"=>$PName1,
13065 "New_Value"=>$PName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013066 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013067 }
13068 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013069 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013070 foreach my $SubProblemType (keys(%SubProblems))
13071 { # add new problems, remove false alarms
13072 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
13073 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
13074 if($SubProblemType eq "Parameter_Type")
13075 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013076 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013077 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013078 if(my $RA = addedQual($Old_Value, $New_Value, "restrict"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013079 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013080 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
13081 if($Level eq "Source"
13082 and cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013083 delete($SubProblems{$SubProblemType});
13084 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013085 }
13086 elsif(my $RR = removedQual($Old_Value, $New_Value, "restrict"))
13087 {
13088 %{$SubProblems{"Parameter_Became_NonRestrict"}} = %{$SubProblems{$SubProblemType}};
13089 if($Level eq "Source"
13090 and cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013091 delete($SubProblems{$SubProblemType});
13092 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013093 }
13094 }
13095 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
13096 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
13097 { # int to "int const"
13098 delete($SubProblems{$SubProblemType});
13099 }
13100 if($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
13101 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
13102 { # "int const" to int
13103 delete($SubProblems{$SubProblemType});
13104 }
13105 }
13106 }
13107 foreach my $SubProblemType (keys(%SubProblems))
13108 { # modify/register problems
13109 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
13110 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013111 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
13112 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013113 my $NewProblemType = $SubProblemType;
13114 if($Old_Value eq "..." and $New_Value ne "...")
13115 { # change from "..." to "int"
13116 if($ParamPos1==0)
13117 { # ISO C requires a named argument before "..."
13118 next;
13119 }
13120 $NewProblemType = "Parameter_Became_NonVaList";
13121 }
13122 elsif($New_Value eq "..." and $Old_Value ne "...")
13123 { # change from "int" to "..."
13124 if($ParamPos2==0)
13125 { # ISO C requires a named argument before "..."
13126 next;
13127 }
13128 $NewProblemType = "Parameter_Became_VaList";
13129 }
13130 elsif($SubProblemType eq "Parameter_Type"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013131 and removedQual($Old_Value, $New_Value, "const"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013132 { # parameter: "const" to non-"const"
13133 $NewProblemType = "Parameter_Became_Non_Const";
13134 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013135 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013136 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013137 {
13138 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013139 if($Arch1 eq "unknown"
13140 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013141 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013142 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013143 ($Arch1, $Arch2) = ("unknown", "unknown");
13144 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013145 my (%Conv1, %Conv2) = ();
13146 if($UseConv_Real{1} and $UseConv_Real{1})
13147 { # real
13148 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
13149 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
13150 }
13151 else
13152 { # model
13153 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13154 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13155 }
13156 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013157 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013158 if($Conv1{"Method"} eq "stack")
13159 {
13160 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
13161 $NewProblemType = "Parameter_Type_And_Stack";
13162 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013163 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013164 elsif($Conv1{"Method"} eq "reg")
13165 {
13166 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
13167 $NewProblemType = "Parameter_Type_And_Register";
13168 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013169 }
13170 }
13171 else
13172 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013173 if($Conv1{"Method"} eq "stack") {
13174 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013175 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013176 elsif($Conv1{"Method"} eq "register") {
13177 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013178 }
13179 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013180 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
13181 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013182 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013183 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013184 "Target"=>$PName1,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013185 "Param_Pos"=>$ParamPos1,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013186 "New_Signature"=>get_Signature($Symbol, 2) );
13187 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013188 }
13189 @RecurTypes = ();
13190 # checking type definition changes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013191 my %SubProblems_Merge = mergeTypes($PType1_Id, $PType2_Id, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013192 foreach my $SubProblemType (keys(%SubProblems_Merge))
13193 {
13194 foreach my $SubLocation (keys(%{$SubProblems_Merge{$SubProblemType}}))
13195 {
13196 my $NewProblemType = $SubProblemType;
13197 if($SubProblemType eq "DataType_Size")
13198 {
13199 my $InitialType_Type = $SubProblems_Merge{$SubProblemType}{$SubLocation}{"InitialType_Type"};
13200 if($InitialType_Type!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
13201 { # stack has been affected
13202 $NewProblemType = "DataType_Size_And_Stack";
13203 }
13204 }
13205 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013206 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013207 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013208 "Param_Pos"=>$ParamPos1,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013209 "Param_Name"=>$PName1 );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013210 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation}}{keys(%{$SubProblems_Merge{$SubProblemType}{$SubLocation}})} = values %{$SubProblems_Merge{$SubProblemType}{$SubLocation}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013211 if($SubLocation!~/\-\>/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013212 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation}{"Start_Type_Name"} = $TypeInfo{1}{$PType1_Id}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013213 }
13214 }
13215 }
13216}
13217
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013218sub find_ParamPair_Pos_byName($$$)
13219{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013220 my ($Name, $Symbol, $LibVersion) = @_;
13221 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013222 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013223 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
13224 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013225 {
13226 return $ParamPos;
13227 }
13228 }
13229 return "lost";
13230}
13231
13232sub find_ParamPair_Pos_byTypeAndPos($$$$$)
13233{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013234 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013235 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013236 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013237 {
13238 next if($Order eq "backward" and $ParamPos>$MediumPos);
13239 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013240 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
13241 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013242 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013243 push(@Positions, $ParamPos);
13244 }
13245 }
13246 return @Positions;
13247}
13248
13249sub getTypeIdByName($$)
13250{
13251 my ($TypeName, $Version) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013252 return $TName_Tid{$Version}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013253}
13254
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013255sub checkFormatChange($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013256{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013257 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013258 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
13259 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013260 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
13261 { # equal types
13262 return 0;
13263 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013264 if($Type1_Pure{"Name"} eq "void")
13265 { # from void* to something
13266 return 0;
13267 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013268 if($Type1_Pure{"Name"}=~/\*/
13269 or $Type2_Pure{"Name"}=~/\*/)
13270 { # compared in detectTypeChange()
13271 return 0;
13272 }
13273 my %FloatType = map {$_=>1} (
13274 "float",
13275 "double",
13276 "long double"
13277 );
13278 if($Type1_Pure{"Type"} ne $Type2_Pure{"Type"})
13279 { # different types
13280 if($Type1_Pure{"Type"} eq "Intrinsic"
13281 and $Type2_Pure{"Type"} eq "Enum")
13282 { # "int" to "enum"
13283 return 0;
13284 }
13285 elsif($Type2_Pure{"Type"} eq "Intrinsic"
13286 and $Type1_Pure{"Type"} eq "Enum")
13287 { # "enum" to "int"
13288 return 0;
13289 }
13290 else
13291 { # "union" to "struct"
13292 # ...
13293 return 1;
13294 }
13295 }
13296 else
13297 {
13298 if($Type1_Pure{"Type"} eq "Intrinsic")
13299 {
13300 if($FloatType{$Type1_Pure{"Name"}}
13301 or $FloatType{$Type2_Pure{"Name"}})
13302 { # "float" to "double"
13303 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013304 if($Level eq "Source")
13305 { # Safe
13306 return 0;
13307 }
13308 else {
13309 return 1;
13310 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013311 }
13312 }
13313 elsif($Type1_Pure{"Type"}=~/Class|Struct|Union|Enum/)
13314 {
13315 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
13316 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040013317 if(not @Membs2)
13318 { # private
13319 return 0;
13320 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013321 if($#Membs1!=$#Membs2)
13322 { # different number of elements
13323 return 1;
13324 }
13325 if($Type1_Pure{"Type"} eq "Enum")
13326 {
13327 foreach my $Pos (@Membs1)
13328 { # compare elements by name and value
13329 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
13330 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
13331 { # different names
13332 return 1;
13333 }
13334 }
13335 }
13336 else
13337 {
13338 foreach my $Pos (@Membs1)
13339 { # compare elements by type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013340 my $MT1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}{"Name"};
13341 my $MT2 = $TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}{"Name"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040013342
13343 $MT1 = uncover_typedefs($MT1, 1);
13344 $MT2 = uncover_typedefs($MT2, 2);
13345
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013346 if($MT1 ne $MT2)
13347 { # different types
Andrey Ponomarenko2956b972012-11-14 19:16:16 +040013348 if(not isAnon($MT1) and not isAnon($MT2)) {
13349 return 1;
13350 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013351 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013352 if($Level eq "Source")
13353 {
13354 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
13355 { # different names
13356 return 1;
13357 }
13358 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013359 }
13360 }
13361 }
13362 }
13363 return 0;
13364}
13365
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013366sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013367{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013368 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013369 if(not $Type1_Id or not $Type2_Id) {
13370 return ();
13371 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013372 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013373 my %Type1 = get_Type($Type1_Id, 1);
13374 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013375 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
13376 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
13377 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
13378 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 +040013379
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013380 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
13381 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013382 return () if(not $Type1{"Name"} or not $Type2{"Name"});
13383 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
13384 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
13385 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
13386 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
13387 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
13388 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013389 if($Type1{"Name"} eq $Type2{"Name"})
13390 {
13391 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
13392 { # will be reported in mergeTypes() as typedef problem
13393 return ();
13394 }
13395 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
13396 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
13397 if(%Typedef_1 and %Typedef_2)
13398 {
13399 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
13400 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
13401 { # const Typedef
13402 return ();
13403 }
13404 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013405 }
13406 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
13407 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013408 if($Level eq "Binary"
13409 and $Type1_Base{"Size"} ne $Type2_Base{"Size"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013410 and $Type1_Base{"Size"} and $Type2_Base{"Size"})
13411 {
13412 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
13413 "Old_Value"=>$Type1_Base{"Name"},
13414 "New_Value"=>$Type2_Base{"Name"},
13415 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
13416 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE,
13417 "InitialType_Type"=>$Type1_Pure{"Type"});
13418 }
13419 else
13420 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013421 if(checkFormatChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013422 { # format change
13423 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
13424 "Old_Value"=>$Type1_Base{"Name"},
13425 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013426 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
13427 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013428 "InitialType_Type"=>$Type1_Pure{"Type"});
13429 }
13430 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
13431 {
13432 %{$LocalProblems{$Prefix."_BaseType"}}=(
13433 "Old_Value"=>$Type1_Base{"Name"},
13434 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013435 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
13436 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013437 "InitialType_Type"=>$Type1_Pure{"Type"});
13438 }
13439 }
13440 }
13441 }
13442 elsif($Type1{"Name"} ne $Type2{"Name"})
13443 { # type change
13444 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
13445 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013446 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013447 and $Type1_Pure{"Name"} eq "void")
13448 {
13449 %{$LocalProblems{"Return_Type_From_Void"}}=(
13450 "New_Value"=>$Type2{"Name"},
13451 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE,
13452 "InitialType_Type"=>$Type1_Pure{"Type"});
13453 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013454 elsif($Prefix eq "Return"
13455 and $Type2_Pure{"Name"} eq "void")
13456 {
13457 %{$LocalProblems{"Return_Type_Became_Void"}}=(
13458 "Old_Value"=>$Type1{"Name"},
13459 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
13460 "InitialType_Type"=>$Type1_Pure{"Type"});
13461 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013462 else
13463 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013464 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013465 and $Type1{"Size"} and $Type2{"Size"}
13466 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013467 {
13468 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
13469 "Old_Value"=>$Type1{"Name"},
13470 "New_Value"=>$Type2{"Name"},
13471 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
13472 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE,
13473 "InitialType_Type"=>$Type1_Pure{"Type"});
13474 }
13475 else
13476 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013477 if(checkFormatChange($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013478 { # format change
13479 %{$LocalProblems{$Prefix."_Type_Format"}}=(
13480 "Old_Value"=>$Type1{"Name"},
13481 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013482 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
13483 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013484 "InitialType_Type"=>$Type1_Pure{"Type"});
13485 }
13486 elsif(tNameLock($Type1_Id, $Type2_Id))
13487 { # FIXME: correct this condition
13488 %{$LocalProblems{$Prefix."_Type"}}=(
13489 "Old_Value"=>$Type1{"Name"},
13490 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013491 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
13492 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013493 "InitialType_Type"=>$Type1_Pure{"Type"});
13494 }
13495 }
13496 }
13497 }
13498 }
13499 if($Type1_PLevel!=$Type2_PLevel)
13500 {
13501 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
13502 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
13503 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013504 if($Level eq "Source")
13505 {
13506 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013507 "Old_Value"=>$Type1_PLevel,
13508 "New_Value"=>$Type2_PLevel);
13509 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013510 else
13511 {
13512 if($Type2_PLevel>$Type1_PLevel) {
13513 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
13514 "Old_Value"=>$Type1_PLevel,
13515 "New_Value"=>$Type2_PLevel);
13516 }
13517 else {
13518 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
13519 "Old_Value"=>$Type1_PLevel,
13520 "New_Value"=>$Type2_PLevel);
13521 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013522 }
13523 }
13524 }
13525 if($Type1_Pure{"Type"} eq "Array")
13526 { # base_type[N] -> base_type[N]
13527 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013528 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013529 foreach my $SubProblemType (keys(%SubProblems))
13530 {
13531 $SubProblemType=~s/_Type/_BaseType/g;
13532 next if(defined $LocalProblems{$SubProblemType});
13533 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
13534 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
13535 }
13536 }
13537 }
13538 return %LocalProblems;
13539}
13540
13541sub tNameLock($$)
13542{
13543 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013544 my $Changed = 0;
13545 if(differentDumps("G"))
13546 { # different GCC versions
13547 $Changed = 1;
13548 }
13549 elsif(differentDumps("V"))
13550 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013551 if(not checkDump(1, "2.20")
13552 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013553 { # latest names update
13554 # 2.6: added restrict qualifier
13555 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013556 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013557 $Changed = 1;
13558 }
13559 }
13560 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013561 { # different formats
13562 if($UseOldDumps)
13563 { # old dumps
13564 return 0;
13565 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013566 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
13567 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013568
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013569 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
13570 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013571
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013572 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013573 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013574 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013575 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013576 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013577 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013578 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013579 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013580 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
13581 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
13582 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013583 { # equal base types
13584 return 0;
13585 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013586
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013587 if(not checkDump(1, "2.13")
13588 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013589 { # broken array names in ABI dumps < 2.13
13590 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013591 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013592 return 0;
13593 }
13594 }
13595
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013596 if(not checkDump(1, "2.6")
13597 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013598 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013599 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013600 and $TN2=~/\brestrict\b/) {
13601 return 0;
13602 }
13603 }
13604
13605 if(not checkDump(1, "2.20")
13606 or not checkDump(2, "2.20"))
13607 { # added restrict attribute in 2.6
13608 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
13609 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013610 return 0;
13611 }
13612 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013613 }
13614 return 1;
13615}
13616
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013617sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013618{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013619 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013620 if(defined $Cache{"differentDumps"}{$Check}) {
13621 return $Cache{"differentDumps"}{$Check};
13622 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013623 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013624 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013625 if($Check eq "G")
13626 {
13627 if(getGccVersion(1) ne getGccVersion(2))
13628 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013629 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013630 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013631 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013632 if($Check eq "V")
13633 {
13634 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
13635 formatVersion($UsedDump{2}{"V"}, 2))!=0)
13636 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013637 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013638 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013639 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013640 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013641 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013642}
13643
13644sub formatVersion($$)
13645{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013646 my ($V, $Digits) = @_;
13647 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013648 return join(".", splice(@Elems, 0, $Digits));
13649}
13650
13651sub htmlSpecChars($)
13652{
13653 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040013654 if(not $Str) {
13655 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013656 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013657 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
13658 $Str=~s/</&lt;/g;
13659 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
13660 $Str=~s/>/&gt;/g;
13661 $Str=~s/([^ ])( )([^ ])/$1\@ALONE_SP\@$3/g;
13662 $Str=~s/ /&#160;/g; # &nbsp;
13663 $Str=~s/\@ALONE_SP\@/ /g;
13664 $Str=~s/\n/<br\/>/g;
13665 $Str=~s/\"/&quot;/g;
13666 $Str=~s/\'/&#39;/g;
13667 return $Str;
13668}
13669
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040013670sub xmlSpecChars($)
13671{
13672 my $Str = $_[0];
13673 if(not $Str) {
13674 return $Str;
13675 }
13676
13677 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
13678 $Str=~s/</&lt;/g;
13679 $Str=~s/>/&gt;/g;
13680
13681 $Str=~s/\"/&quot;/g;
13682 $Str=~s/\'/&#39;/g;
13683
13684 return $Str;
13685}
13686
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040013687sub xmlSpecChars_R($)
13688{
13689 my $Str = $_[0];
13690 if(not $Str) {
13691 return $Str;
13692 }
13693
13694 $Str=~s/&amp;/&/g;
13695 $Str=~s/&lt;/</g;
13696 $Str=~s/&gt;/>/g;
13697
13698 $Str=~s/&quot;/"/g;
13699 $Str=~s/&#39;/'/g;
13700
13701 return $Str;
13702}
13703
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013704sub black_name($)
13705{
13706 my $Name = $_[0];
13707 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
13708}
13709
13710sub highLight_Signature($)
13711{
13712 my $Signature = $_[0];
13713 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
13714}
13715
13716sub highLight_Signature_Italic_Color($)
13717{
13718 my $Signature = $_[0];
13719 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
13720}
13721
13722sub separate_symbol($)
13723{
13724 my $Symbol = $_[0];
13725 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
13726 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
13727 ($Name, $Spec, $Ver) = ($1, $2, $3);
13728 }
13729 return ($Name, $Spec, $Ver);
13730}
13731
13732sub cut_f_attrs($)
13733{
13734 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
13735 return $2;
13736 }
13737 return "";
13738}
13739
13740sub highLight_Signature_PPos_Italic($$$$$)
13741{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013742 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
13743 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013744 if($CheckObjectsOnly) {
13745 $ItalicParams=$ColorParams=0;
13746 }
13747 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
13748 my $Return = "";
13749 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
13750 $Return = $2;
13751 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013752 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013753 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013754 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013755 $Signature = htmlSpecChars($Signature);
13756 $Signature=~s!(\[data\])!<span style='color:Black;font-weight:normal;'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013757 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013758 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013759 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013760 }
13761 return $Signature;
13762 }
13763 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
13764 $Begin.=" " if($Begin!~/ \Z/);
13765 $End = cut_f_attrs($Signature);
13766 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040013767 my ($Short, $Params) = split_Signature($Signature);
13768 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013769 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013770 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013771 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013772 $Part=~s/\A\s+|\s+\Z//g;
13773 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
13774 if($Part=~/\([\*]+(\w+)\)/i) {
13775 $ParamName = $1;#func-ptr
13776 }
13777 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
13778 $ParamName = $1;
13779 }
13780 if(not $ParamName) {
13781 push(@Parts, $Part_Styled);
13782 next;
13783 }
13784 if($ItalicParams and not $TName_Tid{1}{$Part}
13785 and not $TName_Tid{2}{$Part})
13786 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013787 my $Style = "param";
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013788 if($Param_Pos ne ""
13789 and $Pos==$Param_Pos) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013790 $Style = "focus_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013791 }
13792 elsif($ColorParams) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013793 $Style = "color_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013794 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013795 $Part_Styled =~ s!(\W)$ParamName([\,\)]|\Z)!$1<span class=\'$Style\'>$ParamName</span>$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013796 }
13797 $Part_Styled=~s/,(\w)/, $1/g;
13798 push(@Parts, $Part_Styled);
13799 }
13800 if(@Parts)
13801 {
13802 foreach my $Num (0 .. $#Parts)
13803 {
13804 if($Num==$#Parts)
13805 { # add ")" to the last parameter
13806 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
13807 }
13808 elsif(length($Parts[$Num])<=45) {
13809 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
13810 }
13811 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013812 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013813 }
13814 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013815 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013816 }
13817 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013818 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013819 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013820 $Signature=~s!\[\]![&#160;]!g;
13821 $Signature=~s!operator=!operator&#160;=!g;
13822 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='sym_kind'>$1</span>!g;
13823 return $Signature.(($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013824}
13825
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040013826sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013827{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040013828 my $Signature = $_[0];
13829 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
13830 {
13831 $Signature=~s/\A\Q$ShortName\E\(//g;
13832 cut_f_attrs($Signature);
13833 $Signature=~s/\)\Z//;
13834 return ($ShortName, $Signature);
13835 }
13836
13837 # error
13838 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013839}
13840
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040013841sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013842{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040013843 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013844 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013845 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
13846 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013847 foreach my $Pos (0 .. length($Params) - 1)
13848 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013849 my $S = substr($Params, $Pos, 1);
13850 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040013851 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013852 }
13853 if($S eq "," and
13854 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013855 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013856 if($Comma)
13857 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013858 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013859 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013860 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013861 }
13862 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013863 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013864 }
13865 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040013866 if(not $Sp)
13867 { # remove spaces
13868 foreach (@Parts)
13869 {
13870 s/\A //g;
13871 s/ \Z//g;
13872 }
13873 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013874 return @Parts;
13875}
13876
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013877sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013878{
13879 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013880 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013881 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013882 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
13883 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013884 $Center+=length($1);
13885 }
13886 foreach my $Pos (0 .. length($Sign)-1)
13887 {
13888 my $S = substr($Sign, $Pos, 1);
13889 if($S eq $Target)
13890 {
13891 if($B{"("}==$B{")"}
13892 and $B{"<"}==$B{">"}) {
13893 return $Center;
13894 }
13895 }
13896 if(defined $B{$S}) {
13897 $B{$S}+=1;
13898 }
13899 $Center+=1;
13900 }
13901 return 0;
13902}
13903
13904sub appendFile($$)
13905{
13906 my ($Path, $Content) = @_;
13907 return if(not $Path);
13908 if(my $Dir = get_dirname($Path)) {
13909 mkpath($Dir);
13910 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013911 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013912 print FILE $Content;
13913 close(FILE);
13914}
13915
13916sub writeFile($$)
13917{
13918 my ($Path, $Content) = @_;
13919 return if(not $Path);
13920 if(my $Dir = get_dirname($Path)) {
13921 mkpath($Dir);
13922 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013923 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013924 print FILE $Content;
13925 close(FILE);
13926}
13927
13928sub readFile($)
13929{
13930 my $Path = $_[0];
13931 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013932 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013933 local $/ = undef;
13934 my $Content = <FILE>;
13935 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013936 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013937 $Content=~s/\r/\n/g;
13938 }
13939 return $Content;
13940}
13941
13942sub get_filename($)
13943{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013944 if(defined $Cache{"get_filename"}{$_[0]}) {
13945 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013946 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013947 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
13948 return ($Cache{"get_filename"}{$_[0]}=$1);
13949 }
13950 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013951}
13952
13953sub get_dirname($)
13954{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013955 if(defined $Cache{"get_dirname"}{$_[0]}) {
13956 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013957 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013958 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
13959 return ($Cache{"get_dirname"}{$_[0]}=$1);
13960 }
13961 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013962}
13963
13964sub separate_path($) {
13965 return (get_dirname($_[0]), get_filename($_[0]));
13966}
13967
13968sub esc($)
13969{
13970 my $Str = $_[0];
13971 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
13972 return $Str;
13973}
13974
13975sub readLineNum($$)
13976{
13977 my ($Path, $Num) = @_;
13978 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013979 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013980 foreach (1 ... $Num) {
13981 <FILE>;
13982 }
13983 my $Line = <FILE>;
13984 close(FILE);
13985 return $Line;
13986}
13987
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013988sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013989{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013990 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013991 return () if(not $Path or not -f $Path);
13992 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013993 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
13994 {
13995 foreach my $AttrVal (split(/;/, $1))
13996 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013997 if($AttrVal=~/(.+):(.+)/)
13998 {
13999 my ($Name, $Value) = ($1, $2);
14000 $Attributes{$Name} = $Value;
14001 }
14002 }
14003 }
14004 return \%Attributes;
14005}
14006
14007sub is_abs($) {
14008 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
14009}
14010
14011sub get_abs_path($)
14012{ # abs_path() should NOT be called for absolute inputs
14013 # because it can change them
14014 my $Path = $_[0];
14015 if(not is_abs($Path)) {
14016 $Path = abs_path($Path);
14017 }
14018 return $Path;
14019}
14020
14021sub get_OSgroup()
14022{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014023 my $N = $Config{"osname"};
14024 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014025 return "macos";
14026 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014027 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014028 return "bsd";
14029 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014030 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014031 return "beos";
14032 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014033 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014034 return "symbian";
14035 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014036 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014037 return "windows";
14038 }
14039 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014040 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014041 }
14042}
14043
14044sub getGccVersion($)
14045{
14046 my $LibVersion = $_[0];
14047 if($GCC_VERSION{$LibVersion})
14048 { # dump version
14049 return $GCC_VERSION{$LibVersion};
14050 }
14051 elsif($UsedDump{$LibVersion}{"V"})
14052 { # old-version dumps
14053 return "unknown";
14054 }
14055 my $GccVersion = get_dumpversion($GCC_PATH); # host version
14056 if(not $GccVersion) {
14057 return "unknown";
14058 }
14059 return $GccVersion;
14060}
14061
14062sub showArch($)
14063{
14064 my $Arch = $_[0];
14065 if($Arch eq "arm"
14066 or $Arch eq "mips") {
14067 return uc($Arch);
14068 }
14069 return $Arch;
14070}
14071
14072sub getArch($)
14073{
14074 my $LibVersion = $_[0];
14075 if($CPU_ARCH{$LibVersion})
14076 { # dump version
14077 return $CPU_ARCH{$LibVersion};
14078 }
14079 elsif($UsedDump{$LibVersion}{"V"})
14080 { # old-version dumps
14081 return "unknown";
14082 }
14083 if(defined $Cache{"getArch"}{$LibVersion}) {
14084 return $Cache{"getArch"}{$LibVersion};
14085 }
14086 my $Arch = get_dumpmachine($GCC_PATH); # host version
14087 if(not $Arch) {
14088 return "unknown";
14089 }
14090 if($Arch=~/\A([\w]{3,})(-|\Z)/) {
14091 $Arch = $1;
14092 }
14093 $Arch = "x86" if($Arch=~/\Ai[3-7]86\Z/);
14094 if($OSgroup eq "windows") {
14095 $Arch = "x86" if($Arch=~/win32|mingw32/i);
14096 $Arch = "x86_64" if($Arch=~/win64|mingw64/i);
14097 }
14098 $Cache{"getArch"}{$LibVersion} = $Arch;
14099 return $Arch;
14100}
14101
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014102sub get_Report_Header($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014103{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014104 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014105 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014106 if(getArch(1) ne getArch(2)
14107 or getArch(1) eq "unknown"
14108 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014109 { # don't show architecture in the header
14110 $ArchInfo="";
14111 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014112 my $Report_Header = "<h1><span class='nowrap'>";
14113 if($Level eq "Source") {
14114 $Report_Header .= "Source compatibility";
14115 }
14116 elsif($Level eq "Binary") {
14117 $Report_Header .= "Binary compatibility";
14118 }
14119 else {
14120 $Report_Header .= "API compatibility";
14121 }
14122 $Report_Header .= " report for the <span style='color:Blue;'>$TargetLibraryFName</span> $TargetComponent</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014123 $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>";
14124 if($AppPath) {
14125 $Report_Header .= " <span class='nowrap'>&#160;(relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)</span>";
14126 }
14127 $Report_Header .= "</h1>\n";
14128 return $Report_Header;
14129}
14130
14131sub get_SourceInfo()
14132{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014133 my ($CheckedHeaders, $CheckedLibs) = ("", "");
14134 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014135 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014136 $CheckedHeaders = "<a name='Headers'></a><h2>Header Files (".keys(%{$Registered_Headers{1}}).")</h2><hr/>\n";
14137 $CheckedHeaders .= "<div class='h_list'>\n";
14138 foreach my $Header_Path (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} keys(%{$Registered_Headers{1}}))
14139 {
14140 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
14141 my $Header_Name = get_filename($Identity);
14142 my $Dest_Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
14143 $CheckedHeaders .= $Header_Name.$Dest_Comment."<br/>\n";
14144 }
14145 $CheckedHeaders .= "</div>\n";
14146 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014147 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014148 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014149 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014150 $CheckedLibs = "<a name='Libs'></a><h2>".ucfirst($SLIB_TYPE)." Libraries (".keys(%{$Library_Symbol{1}}).")</h2><hr/>\n";
14151 $CheckedLibs .= "<div class='lib_list'>\n";
14152 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
14153 {
14154 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
14155 $CheckedLibs .= $Library."<br/>\n";
14156 }
14157 $CheckedLibs .= "</div>\n";
14158 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014159 }
14160 return $CheckedHeaders.$CheckedLibs;
14161}
14162
14163sub get_TypeProblems_Count($$$)
14164{
14165 my ($TypeChanges, $TargetPriority, $Level) = @_;
14166 my $Type_Problems_Count = 0;
14167 foreach my $Type_Name (sort keys(%{$TypeChanges}))
14168 {
14169 my %Kinds_Target = ();
14170 foreach my $Kind (keys(%{$TypeChanges->{$Type_Name}}))
14171 {
14172 foreach my $Location (keys(%{$TypeChanges->{$Type_Name}{$Kind}}))
14173 {
14174 my $Target = $TypeChanges->{$Type_Name}{$Kind}{$Location}{"Target"};
14175 my $Priority = getProblemSeverity($Level, $Kind);
14176 next if($Priority ne $TargetPriority);
14177 if($Kinds_Target{$Kind}{$Target}) {
14178 next;
14179 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014180 if(cmpSeverities($Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target}, $Priority))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014181 { # select a problem with the highest priority
14182 next;
14183 }
14184 $Kinds_Target{$Kind}{$Target} = 1;
14185 $Type_Problems_Count += 1;
14186 }
14187 }
14188 }
14189 return $Type_Problems_Count;
14190}
14191
14192sub get_Summary($)
14193{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014194 my $Level = $_[0];
14195 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
14196 $C_Problems_Low, $T_Problems_Medium, $T_Problems_Low, $I_Other, $T_Other) = (0,0,0,0,0,0,0,0,0,0,0);
14197 %{$RESULT{$Level}} = (
14198 "Problems"=>0,
14199 "Warnings"=>0,
14200 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014201 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014202 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014203 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014204 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014205 {
14206 if(not defined $CompatRules{$Level}{$Kind})
14207 { # unknown rule
14208 if(not $UnknownRules{$Level}{$Kind})
14209 { # only one warning
14210 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
14211 $UnknownRules{$Level}{$Kind}=1;
14212 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014213 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014214 }
14215 }
14216 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014217 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014218 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014219 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014220 {
14221 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
14222 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014223 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014224 {
14225 my $Priority = getProblemSeverity($Level, $Kind);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014226 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014227 $Added += 1;
14228 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014229 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014230 {
14231 $Removed += 1;
14232 $TotalAffected{$Level}{$Interface} = $Priority;
14233 }
14234 else
14235 {
14236 if($Priority eq "Safe") {
14237 $I_Other += 1;
14238 }
14239 elsif($Priority eq "High") {
14240 $I_Problems_High += 1;
14241 }
14242 elsif($Priority eq "Medium") {
14243 $I_Problems_Medium += 1;
14244 }
14245 elsif($Priority eq "Low") {
14246 $I_Problems_Low += 1;
14247 }
14248 if(($Priority ne "Low" or $StrictCompat)
14249 and $Priority ne "Safe") {
14250 $TotalAffected{$Level}{$Interface} = $Priority;
14251 }
14252 }
14253 }
14254 }
14255 }
14256 }
14257 my %TypeChanges = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014258 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014259 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014260 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014261 {
14262 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
14263 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014264 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014265 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014266 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
14267 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014268 my $Priority = getProblemSeverity($Level, $Kind);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014269 if(cmpSeverities($Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target}, $Priority))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014270 { # select a problem with the highest priority
14271 next;
14272 }
14273 if(($Priority ne "Low" or $StrictCompat)
14274 and $Priority ne "Safe") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014275 $TotalAffected{$Level}{$Interface} = maxSeverity($TotalAffected{$Level}{$Interface}, $Priority);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014276 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014277 %{$TypeChanges{$Type_Name}{$Kind}{$Location}} = %{$CompatProblems{$Level}{$Interface}{$Kind}{$Location}};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014278 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = maxSeverity($Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target}, $Priority);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014279 }
14280 }
14281 }
14282 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014283
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014284 $T_Problems_High = get_TypeProblems_Count(\%TypeChanges, "High", $Level);
14285 $T_Problems_Medium = get_TypeProblems_Count(\%TypeChanges, "Medium", $Level);
14286 $T_Problems_Low = get_TypeProblems_Count(\%TypeChanges, "Low", $Level);
14287 $T_Other = get_TypeProblems_Count(\%TypeChanges, "Safe", $Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014288
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014289 if($CheckObjectsOnly)
14290 { # only removed exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014291 $RESULT{$Level}{"Affected"} = $Removed*100/keys(%{$Symbol_Library{1}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014292 }
14293 else
14294 { # changed and removed public symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014295 my $SCount = keys(%{$CheckedSymbols{$Level}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014296 if($ExtendedCheck)
14297 { # don't count external_func_0 for constants
14298 $SCount-=1;
14299 }
14300 if($SCount)
14301 {
14302 my %Weight = (
14303 "High" => 100,
14304 "Medium" => 50,
14305 "Low" => 25
14306 );
14307 foreach (keys(%{$TotalAffected{$Level}})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014308 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014309 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014310 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014311 }
14312 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014313 $RESULT{$Level}{"Affected"} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014314 }
14315 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014316 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
14317 if($RESULT{$Level}{"Affected"}>=100) {
14318 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014319 }
14320
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014321 $RESULT{$Level}{"Problems"} += $Removed;
14322 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014323 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014324 if($StrictCompat) {
14325 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
14326 }
14327 else {
14328 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
14329 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014330
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014331 if($C_Problems_Low = keys(%{$ProblemsWithConstants{$Level}}))
14332 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014333 if(defined $CompatRules{$Level}{"Changed_Constant"})
14334 {
14335 if($StrictCompat) {
14336 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
14337 }
14338 else {
14339 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
14340 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014341 }
14342 else
14343 {
14344 printMsg("WARNING", "unknown rule \"Changed_Constant\" (\"$Level\")");
14345 $C_Problems_Low = 0;
14346 }
14347 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014348 if($CheckImpl and $Level eq "Binary")
14349 {
14350 if($StrictCompat) {
14351 $RESULT{$Level}{"Problems"} += keys(%ImplProblems);
14352 }
14353 else {
14354 $RESULT{$Level}{"Warnings"} += keys(%ImplProblems);
14355 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014356 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014357 if($RESULT{$Level}{"Problems"}
14358 and $RESULT{$Level}{"Affected"}) {
14359 $RESULT{$Level}{"Verdict"} = "incompatible";
14360 }
14361 else {
14362 $RESULT{$Level}{"Verdict"} = "compatible";
14363 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014364
14365 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
14366 if(not $TotalTypes)
14367 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014368 $TotalTypes = keys(%{$TName_Tid{1}});
14369 }
14370
14371 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
14372 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
14373
14374 my ($TestInfo, $TestResults, $Problem_Summary) = ();
14375
14376 if($ReportFormat eq "xml")
14377 { # XML
14378 # test info
14379 $TestInfo .= " <library>$TargetLibraryName</library>\n";
14380 $TestInfo .= " <version1>\n";
14381 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
14382 $TestInfo .= " <architecture>$Arch1</architecture>\n";
14383 $TestInfo .= " <gcc>$GccV1</gcc>\n";
14384 $TestInfo .= " </version1>\n";
14385
14386 $TestInfo .= " <version2>\n";
14387 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
14388 $TestInfo .= " <architecture>$Arch2</architecture>\n";
14389 $TestInfo .= " <gcc>$GccV2</gcc>\n";
14390 $TestInfo .= " </version2>\n";
14391 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
14392
14393 # test results
14394 $TestResults .= " <headers>\n";
14395 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} keys(%{$Registered_Headers{1}}))
14396 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014397 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014398 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
14399 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
14400 }
14401 $TestResults .= " </headers>\n";
14402
14403 $TestResults .= " <libs>\n";
14404 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
14405 {
14406 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
14407 $TestResults .= " <name>$Library</name>\n";
14408 }
14409 $TestResults .= " </libs>\n";
14410
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014411 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014412 $TestResults .= " <types>".$TotalTypes."</types>\n";
14413
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014414 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
14415 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014416 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
14417
14418 # problem summary
14419 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
14420 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
14421
14422 $Problem_Summary .= " <problems_with_types>\n";
14423 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
14424 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
14425 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
14426 $Problem_Summary .= " <safe>$T_Other</safe>\n";
14427 $Problem_Summary .= " </problems_with_types>\n";
14428
14429 $Problem_Summary .= " <problems_with_symbols>\n";
14430 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
14431 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
14432 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014433 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014434 $Problem_Summary .= " </problems_with_symbols>\n";
14435
14436 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014437 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014438 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014439 if($CheckImpl and $Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014440 {
14441 $Problem_Summary .= " <impl>\n";
14442 $Problem_Summary .= " <low>".keys(%ImplProblems)."</low>\n";
14443 $Problem_Summary .= " </impl>\n";
14444 }
14445 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
14446
14447 return ($TestInfo.$TestResults.$Problem_Summary, "");
14448 }
14449 else
14450 { # HTML
14451 # test info
14452 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014453 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014454 $TestInfo .= "<tr><th>".ucfirst($TargetComponent)." Name</th><td>$TargetLibraryFName</td></tr>\n";
14455
14456 my (@VInf1, @VInf2, $AddTestInfo) = ();
14457 if($Arch1 ne "unknown"
14458 and $Arch2 ne "unknown")
14459 { # CPU arch
14460 if($Arch1 eq $Arch2)
14461 { # go to the separate section
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014462 $AddTestInfo .= "<tr><th>CPU Type</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014463 }
14464 else
14465 { # go to the version number
14466 push(@VInf1, showArch($Arch1));
14467 push(@VInf2, showArch($Arch2));
14468 }
14469 }
14470 if($GccV1 ne "unknown"
14471 and $GccV2 ne "unknown"
14472 and $OStarget ne "windows")
14473 { # GCC version
14474 if($GccV1 eq $GccV2)
14475 { # go to the separate section
14476 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
14477 }
14478 else
14479 { # go to the version number
14480 push(@VInf1, "gcc ".$GccV1);
14481 push(@VInf2, "gcc ".$GccV2);
14482 }
14483 }
14484 # show long version names with GCC version and CPU architecture name (if different)
14485 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
14486 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
14487 $TestInfo .= $AddTestInfo;
14488 #if($COMMON_LANGUAGE{1}) {
14489 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
14490 #}
14491 if($ExtendedCheck) {
14492 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
14493 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014494 if($JoinReport)
14495 {
14496 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014497 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014498 }
14499 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014500 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014501 }
14502 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014503 $TestInfo .= "</table>\n";
14504
14505 # test results
14506 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014507 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014508
14509 my $Headers_Link = "0";
14510 $Headers_Link = "<a href='#Headers' style='color:Blue;'>".keys(%{$Registered_Headers{1}})."</a>" if(keys(%{$Registered_Headers{1}})>0);
14511 $TestResults .= "<tr><th>Total Header Files</th><td>".($CheckObjectsOnly?"0&#160;(not&#160;analyzed)":$Headers_Link)."</td></tr>\n";
14512
14513 if(not $ExtendedCheck)
14514 {
14515 my $Libs_Link = "0";
14516 $Libs_Link = "<a href='#Libs' style='color:Blue;'>".keys(%{$Library_Symbol{1}})."</a>" if(keys(%{$Library_Symbol{1}})>0);
14517 $TestResults .= "<tr><th>Total ".ucfirst($SLIB_TYPE)." Libraries</th><td>".($CheckHeadersOnly?"0&#160;(not&#160;analyzed)":$Libs_Link)."</td></tr>\n";
14518 }
14519
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014520 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014521
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014522 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014523 if($JoinReport) {
14524 $META_DATA = "kind:".lc($Level).";".$META_DATA;
14525 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014526 $TestResults .= "<tr><th>Verdict</th>";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014527 if($RESULT{$Level}{"Verdict"} eq "incompatible") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014528 $TestResults .= "<td><span style='color:Red;'><b>Incompatible<br/>(".$RESULT{$Level}{"Affected"}."%)</b></span></td>";
14529 }
14530 else {
14531 $TestResults .= "<td><span style='color:Green;'><b>Compatible</b></span></td>";
14532 }
14533 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014534 $TestResults .= "</table>\n";
14535
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014536 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014537 # problem summary
14538 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014539 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014540 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
14541
14542 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014543 if($Added>0)
14544 {
14545 if($JoinReport) {
14546 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
14547 }
14548 else {
14549 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
14550 }
14551 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014552 $META_DATA .= "added:$Added;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014553 $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 +040014554
14555 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014556 if($Removed>0)
14557 {
14558 if($JoinReport) {
14559 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
14560 }
14561 else {
14562 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
14563 }
14564 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014565 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014566 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
14567 $Problem_Summary .= "<td>High</td><td".getStyle("I", "R", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014568
14569 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014570 $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 +040014571 $TH_Link = "n/a" if($CheckObjectsOnly);
14572 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014573 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
14574 $Problem_Summary .= "<td>High</td><td".getStyle("T", "H", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014575
14576 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014577 $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 +040014578 $TM_Link = "n/a" if($CheckObjectsOnly);
14579 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014580 $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 +040014581
14582 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014583 $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 +040014584 $TL_Link = "n/a" if($CheckObjectsOnly);
14585 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014586 $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 +040014587
14588 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014589 $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 +040014590 $IH_Link = "n/a" if($CheckObjectsOnly);
14591 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014592 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
14593 $Problem_Summary .= "<td>High</td><td".getStyle("I", "H", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014594
14595 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014596 $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 +040014597 $IM_Link = "n/a" if($CheckObjectsOnly);
14598 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014599 $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 +040014600
14601 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014602 $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 +040014603 $IL_Link = "n/a" if($CheckObjectsOnly);
14604 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014605 $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 +040014606
14607 my $ChangedConstants_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014608 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low)
14609 {
14610 if($JoinReport) {
14611 $ChangedConstants_Link = "<a href='#".$Level."_Changed_Constants' style='color:Blue;'>$C_Problems_Low</a>";
14612 }
14613 else {
14614 $ChangedConstants_Link = "<a href='#Changed_Constants' style='color:Blue;'>$C_Problems_Low</a>";
14615 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014616 }
14617 $ChangedConstants_Link = "n/a" if($CheckObjectsOnly);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014618 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014619 $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 +040014620
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014621 if($CheckImpl and $Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014622 {
14623 my $ChangedImpl_Link = "0";
14624 $ChangedImpl_Link = "<a href='#Changed_Implementation' style='color:Blue;'>".keys(%ImplProblems)."</a>" if(keys(%ImplProblems)>0);
14625 $ChangedImpl_Link = "n/a" if($CheckHeadersOnly);
14626 $META_DATA .= "changed_implementation:".keys(%ImplProblems).";";
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014627 $Problem_Summary .= "<tr><th>Problems with<br/>Implementation</th><td>Low</td><td".getStyle("Imp", "L", int(keys(%ImplProblems))).">$ChangedImpl_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014628 }
14629 # Safe Changes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014630 if($T_Other and not $CheckObjectsOnly)
14631 {
14632 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014633 $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 +040014634 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014635
14636 if($I_Other and not $CheckObjectsOnly)
14637 {
14638 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014639 $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 +040014640 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014641
14642 $META_DATA .= "tool_version:$TOOL_VERSION";
14643 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014644 # $TestInfo = getLegend().$TestInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014645 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
14646 }
14647}
14648
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014649sub getStyle($$$)
14650{
14651 my ($Subj, $Act, $Num) = @_;
14652 my %Style = (
14653 "A"=>"new",
14654 "R"=>"failed",
14655 "S"=>"passed",
14656 "L"=>"warning",
14657 "M"=>"failed",
14658 "H"=>"failed"
14659 );
14660 if($Num>0) {
14661 return " class='".$Style{$Act}."'";
14662 }
14663 return "";
14664}
14665
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014666sub show_number($)
14667{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014668 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014669 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014670 my $Num = cut_off_number($_[0], 2, 0);
14671 if($Num eq "0")
14672 {
14673 foreach my $P (3 .. 7)
14674 {
14675 $Num = cut_off_number($_[0], $P, 1);
14676 if($Num ne "0") {
14677 last;
14678 }
14679 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014680 }
14681 if($Num eq "0") {
14682 $Num = $_[0];
14683 }
14684 return $Num;
14685 }
14686 return $_[0];
14687}
14688
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014689sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014690{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014691 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014692 if($num!~/\./)
14693 {
14694 $num .= ".";
14695 foreach (1 .. $digs_to_cut-1) {
14696 $num .= "0";
14697 }
14698 }
14699 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
14700 {
14701 foreach (1 .. $digs_to_cut - 1 - length($1)) {
14702 $num .= "0";
14703 }
14704 }
14705 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
14706 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
14707 }
14708 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014709 if($z) {
14710 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
14711 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014712 return $num;
14713}
14714
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014715sub get_Report_ChangedConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014716{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014717 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014718 my $CHANGED_CONSTANTS = "";
14719 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014720 foreach my $Constant (keys(%{$ProblemsWithConstants{$Level}})) {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014721 $ReportMap{$Constants{1}{$Constant}{"Header"}}{$Constant} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014722 }
14723 my $Kind = "Changed_Constant";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014724 if(not defined $CompatRules{$Level}{$Kind}) {
14725 return "";
14726 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014727 if($ReportFormat eq "xml")
14728 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014729 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014730 {
14731 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014732 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014733 {
14734 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014735 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
14736 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
14737 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014738 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014739 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $ProblemsWithConstants{$Level}{$Constant}).">$Change</change>\n";
14740 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $ProblemsWithConstants{$Level}{$Constant}).">$Effect</effect>\n";
14741 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $ProblemsWithConstants{$Level}{$Constant}).">$Overcome</overcome>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014742 $CHANGED_CONSTANTS .= " </problem>\n";
14743 $CHANGED_CONSTANTS .= " </constant>\n";
14744 }
14745 $CHANGED_CONSTANTS .= " </header>\n";
14746 }
14747 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
14748 }
14749 else
14750 { # HTML
14751 my $Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014752 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014753 {
14754 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014755 foreach my $Name (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014756 {
14757 $Number += 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014758 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $ProblemsWithConstants{$Level}{$Name});
14759 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014760 my $Report = "<tr><th>1</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014761 $Report = $ContentDivStart."<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>".$Report."</table><br/>$ContentDivEnd\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014762 $Report = $ContentSpanStart."<span class='extendable'>[+]</span> ".$Name.$ContentSpanEnd."<br/>\n".$Report;
14763 $CHANGED_CONSTANTS .= insertIDs($Report);
14764 }
14765 $CHANGED_CONSTANTS .= "<br/>\n";
14766 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014767 if($CHANGED_CONSTANTS)
14768 {
14769 my $Anchor = "<a name='Changed_Constants'></a>";
14770 if($JoinReport) {
14771 $Anchor = "<a name='".$Level."_Changed_Constants'></a>";
14772 }
14773 $CHANGED_CONSTANTS = $Anchor."<h2>Problems with Constants ($Number)</h2><hr/>\n".$CHANGED_CONSTANTS.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014774 }
14775 }
14776 return $CHANGED_CONSTANTS;
14777}
14778
14779sub get_Report_Impl()
14780{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014781 my $CHANGED_IMPLEMENTATION = "";
14782 my %ReportMap = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014783 foreach my $Interface (sort keys(%ImplProblems))
14784 {
14785 my $HeaderName = $CompleteSignature{1}{$Interface}{"Header"};
14786 my $DyLib = $Symbol_Library{1}{$Interface};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014787 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014788 }
14789 my $Changed_Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014790 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014791 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014792 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014793 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014794 my %NameSpaceSymbols = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014795 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014796 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014797 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014798 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014799 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014800 $CHANGED_IMPLEMENTATION .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014801 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014802 foreach my $Interface (@SortedInterfaces)
14803 {
14804 $Changed_Number += 1;
14805 my $Signature = get_Signature($Interface, 1);
14806 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014807 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014808 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014809 $CHANGED_IMPLEMENTATION .= $ContentSpanStart.highLight_Signature_Italic_Color($Signature).$ContentSpanEnd."<br/>\n".$ContentDivStart."<span class='mangled'>[symbol: <b>$Interface</b>]</span>".$ImplProblems{$Interface}{"Diff"}."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014810 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014811 $CHANGED_IMPLEMENTATION .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014812 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014813 }
14814 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014815 if($CHANGED_IMPLEMENTATION)
14816 {
14817 $CHANGED_IMPLEMENTATION = insertIDs($CHANGED_IMPLEMENTATION);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014818 $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 +040014819 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014820
14821 # clean memory
14822 %ImplProblems = ();
14823
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014824 return $CHANGED_IMPLEMENTATION;
14825}
14826
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014827sub getTitle($$$)
14828{
14829 my ($Header, $Library, $NameSpace) = @_;
14830 my $Title = "";
14831 if($Library and $Library!~/\.\w+\Z/) {
14832 $Library .= " (.$LIB_EXT)";
14833 }
14834 if($Header and $Library)
14835 {
14836 $Title .= "<span class='h_name'>$Header</span>";
14837 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
14838 }
14839 elsif($Library) {
14840 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
14841 }
14842 elsif($Header) {
14843 $Title .= "<span class='h_name'>$Header</span><br/>\n";
14844 }
14845 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014846 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014847 }
14848 return $Title;
14849}
14850
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014851sub get_Report_Added($)
14852{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014853 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014854 my $ADDED_INTERFACES = "";
14855 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014856 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014857 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014858 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014859 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014860 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014861 {
14862 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
14863 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014864 if($Level eq "Source" and $ReportFormat eq "html")
14865 { # do not show library name in HTML report
14866 $DyLib = "";
14867 }
14868 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014869 }
14870 }
14871 }
14872 if($ReportFormat eq "xml")
14873 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014874 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014875 {
14876 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014877 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014878 {
14879 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014880 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014881 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
14882 }
14883 $ADDED_INTERFACES .= " </library>\n";
14884 }
14885 $ADDED_INTERFACES .= " </header>\n";
14886 }
14887 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
14888 }
14889 else
14890 { # HTML
14891 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014892 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014893 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014894 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014895 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014896 my %NameSpaceSymbols = ();
14897 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014898 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014899 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014900 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014901 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014902 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
14903 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014904 foreach my $Interface (@SortedInterfaces)
14905 {
14906 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014907 my $Signature = get_Signature($Interface, 2);
14908 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014909 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014910 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014911 if($Interface=~/\A(_Z|\?)/)
14912 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014913 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014914 $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 +040014915 }
14916 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014917 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014918 }
14919 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014920 else
14921 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014922 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014923 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014924 }
14925 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014926 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014927 }
14928 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014929 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014930 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014931 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014932 }
14933 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014934 if($ADDED_INTERFACES)
14935 {
14936 my $Anchor = "<a name='Added'></a>";
14937 if($JoinReport) {
14938 $Anchor = "<a name='".$Level."_Added'></a>";
14939 }
14940 $ADDED_INTERFACES = $Anchor."<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014941 }
14942 }
14943 return $ADDED_INTERFACES;
14944}
14945
14946sub get_Report_Removed($)
14947{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014948 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014949 my $REMOVED_INTERFACES = "";
14950 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014951 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014952 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014953 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014954 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014955 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014956 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014957 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
14958 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014959 if($Level eq "Source" and $ReportFormat eq "html")
14960 { # do not show library name in HTML report
14961 $DyLib = "";
14962 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014963 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014964 }
14965 }
14966 }
14967 if($ReportFormat eq "xml")
14968 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014969 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014970 {
14971 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014972 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014973 {
14974 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014975 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
14976 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014977 }
14978 $REMOVED_INTERFACES .= " </library>\n";
14979 }
14980 $REMOVED_INTERFACES .= " </header>\n";
14981 }
14982 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
14983 }
14984 else
14985 { # HTML
14986 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014987 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014988 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014989 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014990 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014991 my %NameSpaceSymbols = ();
14992 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014993 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014994 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014995 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014996 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014997 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
14998 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014999 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015000 {
15001 $Removed_Number += 1;
15002 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015003 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015004 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015005 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015006 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015007 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015008 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015009 if($Signature) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015010 $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 +040015011 }
15012 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015013 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015014 }
15015 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015016 else
15017 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015018 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015019 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015020 }
15021 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015022 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015023 }
15024 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015025 }
15026 }
15027 $REMOVED_INTERFACES .= "<br/>\n";
15028 }
15029 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015030 if($REMOVED_INTERFACES)
15031 {
15032 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
15033 if($JoinReport) {
15034 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
15035 }
15036 $REMOVED_INTERFACES = $Anchor."<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015037 }
15038 }
15039 return $REMOVED_INTERFACES;
15040}
15041
15042sub getXmlParams($$)
15043{
15044 my ($Content, $Problem) = @_;
15045 return "" if(not $Content or not $Problem);
15046 my %XMLparams = ();
15047 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
15048 {
15049 my $Macro = "\@".lc($Attr);
15050 if($Content=~/\Q$Macro\E/) {
15051 $XMLparams{lc($Attr)} = $Problem->{$Attr};
15052 }
15053 }
15054 my @PString = ();
15055 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015056 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015057 }
15058 if(@PString) {
15059 return " ".join(" ", @PString);
15060 }
15061 else {
15062 return "";
15063 }
15064}
15065
15066sub addMarkup($)
15067{
15068 my $Content = $_[0];
15069 # auto-markup
15070 $Content=~s/\n[ ]*//; # spaces
15071 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
15072 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015073 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015074 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
15075 if($Content=~/\ANOTE:/)
15076 { # notes
15077 $Content=~s!(NOTE):!<b>$1</b>:!g;
15078 }
15079 else {
15080 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
15081 }
15082 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
15083 my @Keywords = (
15084 "void",
15085 "const",
15086 "static",
15087 "restrict",
15088 "volatile",
15089 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015090 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015091 );
15092 my $MKeys = join("|", @Keywords);
15093 foreach (@Keywords) {
15094 $MKeys .= "|non-".$_;
15095 }
15096 $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 +040015097
15098 # Markdown
15099 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
15100 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015101 return $Content;
15102}
15103
15104sub applyMacroses($$$$)
15105{
15106 my ($Level, $Kind, $Content, $Problem) = @_;
15107 return "" if(not $Content or not $Problem);
15108 $Problem->{"Word_Size"} = $WORD_SIZE{2};
15109 $Content = addMarkup($Content);
15110 # macros
15111 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
15112 {
15113 my $Macro = "\@".lc($Attr);
15114 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015115 if(not defined $Value
15116 or $Value eq "") {
15117 next;
15118 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015119 if($Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015120 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015121 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
15122 $Value=~s/\s\w+(\)|,)/$1/g; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015123 $Value = black_name($Value);
15124 }
15125 elsif($Value=~/\s/) {
15126 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
15127 }
15128 elsif($Value=~/\A\d+\Z/
15129 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
15130 { # bits to bytes
15131 if($Value % $BYTE_SIZE)
15132 { # bits
15133 if($Value==1) {
15134 $Value = "<b>".$Value."</b> bit";
15135 }
15136 else {
15137 $Value = "<b>".$Value."</b> bits";
15138 }
15139 }
15140 else
15141 { # bytes
15142 $Value /= $BYTE_SIZE;
15143 if($Value==1) {
15144 $Value = "<b>".$Value."</b> byte";
15145 }
15146 else {
15147 $Value = "<b>".$Value."</b> bytes";
15148 }
15149 }
15150 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015151 else
15152 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015153 $Value = "<b>".htmlSpecChars($Value)."</b>";
15154 }
15155 $Content=~s/\Q$Macro\E/$Value/g;
15156 }
15157
15158 if($Content=~/(\A|[^\@\w])\@\w/)
15159 {
15160 if(not $IncompleteRules{$Level}{$Kind})
15161 { # only one warning
15162 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
15163 $IncompleteRules{$Level}{$Kind} = 1;
15164 }
15165 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015166 return $Content;
15167}
15168
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015169sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015170{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015171 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015172 my $INTERFACE_PROBLEMS = "";
15173 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015174 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015175 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015176 my ($SN, $SS, $SV) = separate_symbol($Symbol);
15177 if($SV and defined $CompatProblems{$Level}{$SN}) {
15178 next;
15179 }
15180 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015181 {
15182 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015183 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015184 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015185 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
15186 my $DyLib = $Symbol_Library{1}{$Symbol};
15187 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015188 { # Symbol with Version
15189 $DyLib = $Symbol_Library{1}{$VSym};
15190 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015191 if(not $DyLib)
15192 { # const global data
15193 $DyLib = "";
15194 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015195 if($Level eq "Source" and $ReportFormat eq "html")
15196 { # do not show library name in HTML report
15197 $DyLib = "";
15198 }
15199 %{$SymbolChanges{$Symbol}{$Kind}} = %{$CompatProblems{$Level}{$Symbol}{$Kind}};
15200 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015201 {
15202 my $Priority = getProblemSeverity($Level, $Kind);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015203 if($Priority ne $TargetSeverity) {
15204 delete($SymbolChanges{$Symbol}{$Kind}{$Location});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015205 }
15206 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015207 if(not keys(%{$SymbolChanges{$Symbol}{$Kind}}))
15208 {
15209 delete($SymbolChanges{$Symbol}{$Kind});
15210 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015211 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015212 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015213 }
15214 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015215 if(not keys(%{$SymbolChanges{$Symbol}})) {
15216 delete($SymbolChanges{$Symbol});
15217 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015218 }
15219 if($ReportFormat eq "xml")
15220 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015221 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015222 {
15223 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015224 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015225 {
15226 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
15227 foreach my $Symbol (sort {lc($tr_name{$a}) cmp lc($tr_name{$b})} keys(%SymbolChanges))
15228 {
15229 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
15230 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
15231 {
15232 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
15233 {
15234 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015235 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015236 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
15237 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
15238 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
15239 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
15240 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
15241 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
15242 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
15243 $INTERFACE_PROBLEMS .= " </problem>\n";
15244 }
15245 }
15246 $INTERFACE_PROBLEMS .= " </symbol>\n";
15247 }
15248 $INTERFACE_PROBLEMS .= " </library>\n";
15249 }
15250 $INTERFACE_PROBLEMS .= " </header>\n";
15251 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015252 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015253 }
15254 else
15255 { # HTML
15256 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015257 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015258 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015259 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015260 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015261 my (%NameSpaceSymbols, %NewSignature) = ();
15262 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015263 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015264 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015265 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015266 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015267 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
15268 my @SortedInterfaces = sort {lc($tr_name{$a}) cmp lc($tr_name{$b})} keys(%{$NameSpaceSymbols{$NameSpace}});
15269 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015270 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015271 my $Signature = get_Signature($Symbol, 1);
15272 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015273 my $ProblemNum = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015274 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015275 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015276 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015277 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015278 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015279 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015280 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015281 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015282 }
15283 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
15284 {
15285 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015286 $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 +040015287 $ProblemNum += 1;
15288 $ProblemsNum += 1;
15289 }
15290 }
15291 }
15292 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015293 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015294 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015295 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015296 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015297 $INTERFACE_PROBLEMS .= highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015298 }
15299 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015300 $INTERFACE_PROBLEMS .= $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015301 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015302 $INTERFACE_PROBLEMS .= " ($ProblemNum)".$ContentSpanEnd."<br/>\n";
15303 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
15304 if($NewSignature{$Symbol})
15305 { # argument list changed to
15306 $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 +040015307 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015308 if($Symbol=~/\A(_Z|\?)/) {
15309 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
15310 }
15311 $INTERFACE_PROBLEMS .= "<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>$SYMBOL_REPORT</table><br/>\n";
15312 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015313 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015314 $INTERFACE_PROBLEMS=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015315 }
15316 }
15317 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015318 $INTERFACE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015319 }
15320 }
15321 }
15322 if($INTERFACE_PROBLEMS)
15323 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015324 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
15325 my $Title = "Problems with Symbols, $TargetSeverity Severity";
15326 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015327 { # Safe Changes
15328 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015329 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015330 $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 +040015331 }
15332 }
15333 return $INTERFACE_PROBLEMS;
15334}
15335
15336sub get_Report_TypeProblems($$)
15337{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015338 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015339 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015340 my (%ReportMap, %TypeChanges) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015341 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015342 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015343 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015344 {
15345 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15346 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015347 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015348 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015349 my $TypeName = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015350 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015351 my $Severity = getProblemSeverity($Level, $Kind);
15352 if($Severity eq "Safe"
15353 and $TargetSeverity ne "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015354 next;
15355 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015356
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015357 if(cmpSeverities($Type_MaxSeverity{$Level}{$TypeName}{$Kind}{$Target}, $Severity))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015358 { # select a problem with the highest priority
15359 next;
15360 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015361 %{$TypeChanges{$TypeName}{$Kind}{$Location}} = %{$CompatProblems{$Level}{$Interface}{$Kind}{$Location}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015362 }
15363 }
15364 }
15365 }
15366 my %Kinds_Locations = ();
15367 foreach my $TypeName (keys(%TypeChanges))
15368 {
15369 my %Kinds_Target = ();
15370 foreach my $Kind (sort keys(%{$TypeChanges{$TypeName}}))
15371 {
15372 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
15373 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015374 my $Severity = getProblemSeverity($Level, $Kind);
15375 if($Severity ne $TargetSeverity)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015376 { # other priority
15377 delete($TypeChanges{$TypeName}{$Kind}{$Location});
15378 next;
15379 }
15380 $Kinds_Locations{$TypeName}{$Kind}{$Location} = 1;
15381 my $Target = $TypeChanges{$TypeName}{$Kind}{$Location}{"Target"};
15382 if($Kinds_Target{$Kind}{$Target})
15383 { # duplicate target
15384 delete($TypeChanges{$TypeName}{$Kind}{$Location});
15385 next;
15386 }
15387 $Kinds_Target{$Kind}{$Target} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015388 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015389 $ReportMap{$HeaderName}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015390 }
15391 if(not keys(%{$TypeChanges{$TypeName}{$Kind}})) {
15392 delete($TypeChanges{$TypeName}{$Kind});
15393 }
15394 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015395 if(not keys(%{$TypeChanges{$TypeName}})) {
15396 delete($TypeChanges{$TypeName});
15397 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015398 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015399 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 +040015400 if($ReportFormat eq "xml")
15401 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015402 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015403 {
15404 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015405 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015406 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015407 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015408 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
15409 {
15410 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
15411 {
15412 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
15413 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
15414 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
15415 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
15416 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
15417 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
15418 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
15419 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
15420 $TYPE_PROBLEMS .= " </problem>\n";
15421 }
15422 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015423 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015424 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015425 $TYPE_PROBLEMS .= showVTables($TypeName);
15426 }
15427 $TYPE_PROBLEMS .= " </type>\n";
15428 }
15429 $TYPE_PROBLEMS .= " </header>\n";
15430 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015431 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015432 }
15433 else
15434 { # HTML
15435 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015436 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015437 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015438 my (%NameSpace_Type) = ();
15439 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015440 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015441 }
15442 foreach my $NameSpace (sort keys(%NameSpace_Type))
15443 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015444 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015445 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 +040015446 foreach my $TypeName (@SortedTypes)
15447 {
15448 my $ProblemNum = 1;
15449 my $TYPE_REPORT = "";
15450 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
15451 {
15452 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
15453 {
15454 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
15455 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
15456 {
15457 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
15458 $TYPE_REPORT .= "<tr><th>$ProblemNum</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
15459 $ProblemNum += 1;
15460 $ProblemsNum += 1;
15461 }
15462 }
15463 }
15464 $ProblemNum -= 1;
15465 if($TYPE_REPORT)
15466 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015467 my $Affected = getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015468 my $ShowVTables = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015469 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015470 $ShowVTables = showVTables($TypeName);
15471 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015472
15473 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ".show_Type($TypeName, 1, 1)." ($ProblemNum)".$ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015474 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
15475 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
15476 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
15477 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015478 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015479 $TYPE_PROBLEMS=~s/\b\Q$NameSpace\E::(\w|\~)/$1/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015480 }
15481 }
15482 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015483 $TYPE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015484 }
15485 }
15486 if($TYPE_PROBLEMS)
15487 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015488 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
15489 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015490 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015491 { # Safe Changes
15492 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015493 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015494 $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 +040015495 }
15496 }
15497 return $TYPE_PROBLEMS;
15498}
15499
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015500sub show_Type($$$)
15501{
15502 my ($Name, $Html, $LibVersion) = @_;
15503 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
15504 $TType = lc($TType);
15505 if($TType=~/struct|union|enum/) {
15506 $Name=~s/\A\Q$TType\E //g;
15507 }
15508 if($Html) {
15509 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
15510 }
15511 else {
15512 $Name = $TType." ".$Name;
15513 }
15514 return $Name;
15515}
15516
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015517sub get_Anchor($$$)
15518{
15519 my ($Kind, $Level, $Severity) = @_;
15520 if($JoinReport)
15521 {
15522 if($Severity eq "Safe") {
15523 return "Other_".$Level."_Changes_In_".$Kind."s";
15524 }
15525 else {
15526 return $Kind."_".$Level."_Problems_".$Severity;
15527 }
15528 }
15529 else
15530 {
15531 if($Severity eq "Safe") {
15532 return "Other_Changes_In_".$Kind."s";
15533 }
15534 else {
15535 return $Kind."_Problems_".$Severity;
15536 }
15537 }
15538}
15539
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015540sub showVTables($)
15541{
15542 my $TypeName = $_[0];
15543 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015544 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015545 if(defined $Type1{"VTable"}
15546 and keys(%{$Type1{"VTable"}}))
15547 {
15548 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015549 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015550 if(defined $Type2{"VTable"}
15551 and keys(%{$Type2{"VTable"}}))
15552 {
15553 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
15554 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015555 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015556 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015557 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
15558 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015559 }
15560 my $VTABLES = "";
15561 if($ReportFormat eq "xml")
15562 { # XML
15563 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015564 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015565 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015566 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015567 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
15568 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015569 $VTABLES .= " </entry>\n";
15570 }
15571 $VTABLES .= " </vtable>\n\n";
15572 }
15573 else
15574 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015575 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015576 $VTABLES .= "<tr><th width='2%'>Offset</th>";
15577 $VTABLES .= "<th width='45%'>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
15578 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015579 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015580 {
15581 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015582 if($Entries{$Index}{"E1"} ne $Entries{$Index}{"E2"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015583 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015584 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015585 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015586 $Color1 = " class='failed'";
15587 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015588 }
15589 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015590 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015591 }
15592 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015593 $VTABLES .= "<tr><th>".$Index."</th>\n";
15594 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
15595 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015596 }
15597 $VTABLES .= "</table><br/>\n";
15598 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015599 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015600 }
15601 return $VTABLES;
15602 }
15603 }
15604 return "";
15605}
15606
15607sub simpleVEntry($)
15608{
15609 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015610 if(not defined $VEntry
15611 or $VEntry eq "") {
15612 return "";
15613 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015614 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
15615 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
15616 if($VEntry=~/\A_ZThn.+\Z/) {
15617 $VEntry = "non-virtual thunk";
15618 }
15619 $VEntry=~s/\A\(int \(\*\)\(...\)\)([^\(\d])/$1/i;
15620 # support for old GCC versions
15621 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
15622 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
15623 $VEntry=~s/\A&_Z\Z/& _Z/;
15624 # templates
15625 if($VEntry=~s/ \[with (\w+) = (.+?)(, [^=]+ = .+|])\Z//g)
15626 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
15627 # become std::basic_streambuf<char, ...>::imbue
15628 my ($Pname, $Pval) = ($1, $2);
15629 if($Pname eq "_CharT" and $VEntry=~/\Astd::/)
15630 { # stdc++ typedefs
15631 $VEntry=~s/<$Pname(, [^<>]+|)>/<$Pval>/g;
15632 # FIXME: simplify names using stdcxx typedefs (StdCxxTypedef)
15633 # The typedef info should be added to ABI dumps
15634 }
15635 else
15636 {
15637 $VEntry=~s/<$Pname>/<$Pval>/g;
15638 $VEntry=~s/<$Pname, [^<>]+>/<$Pval, ...>/g;
15639 }
15640 }
15641 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
15642 return $VEntry;
15643}
15644
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015645sub getAffectedSymbols($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015646{
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015647 my ($Level, $Target_TypeName, $Kinds_Locations, $Syms) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015648 my $LIMIT = 1000;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015649 if($#{$Syms}>=10000)
15650 { # reduce size of the report
15651 $LIMIT = 10;
15652 }
15653 my %SProblems = ();
15654 foreach my $Symbol (@{$Syms})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015655 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015656 if(keys(%SProblems)>$LIMIT) {
15657 last;
15658 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015659 if(($Symbol=~/C2E|D2E|D0E/))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015660 { # duplicated problems for C2 constructors, D2 and D0 destructors
15661 next;
15662 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015663 my ($SN, $SS, $SV) = separate_symbol($Symbol);
15664 if($Level eq "Source")
15665 { # remove symbol version
15666 $Symbol=$SN;
15667 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015668 my ($MinPath_Length, $ProblemLocation_Last) = (-1, "");
15669 my $Severity_Max = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015670 my $Signature = get_Signature($Symbol, 1);
15671 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015672 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015673 foreach my $Location (keys(%{$CompatProblems{$Level}{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015674 {
15675 if(not defined $Kinds_Locations->{$Kind}
15676 or not $Kinds_Locations->{$Kind}{$Location}) {
15677 next;
15678 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015679 if($SV and defined $CompatProblems{$Level}{$SN}
15680 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Location})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015681 { # duplicated problems for versioned symbols
15682 next;
15683 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015684 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015685 next if($Type_Name ne $Target_TypeName);
15686
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015687 my $Position = $CompatProblems{$Level}{$Symbol}{$Kind}{$Location}{"Param_Pos"};
15688 my $Param_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Location}{"Param_Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015689 my $Severity = getProblemSeverity($Level, $Kind);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015690 my $Path_Length = 0;
15691 my $ProblemLocation = $Location;
15692 if($Type_Name) {
15693 $ProblemLocation=~s/->\Q$Type_Name\E\Z//g;
15694 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015695 while($ProblemLocation=~/\-\>/g) {
15696 $Path_Length += 1;
15697 }
15698 if($MinPath_Length==-1 or ($Path_Length<=$MinPath_Length and $Severity_Val{$Severity}>$Severity_Max)
15699 or (cmp_locations($ProblemLocation, $ProblemLocation_Last) and $Severity_Val{$Severity}==$Severity_Max))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015700 {
15701 $MinPath_Length = $Path_Length;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015702 $Severity_Max = $Severity_Val{$Severity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015703 $ProblemLocation_Last = $ProblemLocation;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015704 %{$SProblems{$Symbol}} = (
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015705 "Descr"=>getAffectDescription($Level, $Symbol, $Kind, $Location),
15706 "Severity_Max"=>$Severity_Max,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015707 "Signature"=>$Signature,
15708 "Position"=>$Position,
15709 "Param_Name"=>$Param_Name,
15710 "Location"=>$Location
15711 );
15712 }
15713 }
15714 }
15715 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015716 my @Symbols = keys(%SProblems);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015717 @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 +040015718 @Symbols = sort {$SProblems{$b}{"Severity_Max"}<=>$SProblems{$a}{"Severity_Max"}} @Symbols;
15719 if($#Symbols+1>$LIMIT)
15720 { # remove last element
15721 pop(@Symbols);
15722 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015723 my $Affected = "";
15724 if($ReportFormat eq "xml")
15725 { # XML
15726 $Affected .= " <affected>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015727 foreach my $Symbol (@Symbols)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015728 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015729 my $Param_Name = $SProblems{$Symbol}{"Param_Name"};
15730 my $Description = $SProblems{$Symbol}{"Descr"};
15731 my $Location = $SProblems{$Symbol}{"Location"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015732 my $Target = "";
15733 if($Param_Name) {
15734 $Target = " affected=\"param\" param_name=\"$Param_Name\"";
15735 }
15736 elsif($Location=~/\Aretval(\-|\Z)/i) {
15737 $Target = " affected=\"retval\"";
15738 }
15739 elsif($Location=~/\Athis(\-|\Z)/i) {
15740 $Target = " affected=\"this\"";
15741 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015742 $Affected .= " <symbol$Target name=\"$Symbol\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015743 $Affected .= " <comment>".xmlSpecChars($Description)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015744 $Affected .= " </symbol>\n";
15745 }
15746 $Affected .= " </affected>\n";
15747 }
15748 else
15749 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015750 foreach my $Symbol (@Symbols)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015751 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015752 my $Description = $SProblems{$Symbol}{"Descr"};
15753 my $Signature = $SProblems{$Symbol}{"Signature"};
15754 my $Pos = $SProblems{$Symbol}{"Position"};
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040015755 $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 +040015756 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015757 if(keys(%SProblems)>$LIMIT) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015758 $Affected .= "and others ...<br/>";
15759 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015760 $Affected = "<div class='affected'>".$Affected."</div>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015761 if($Affected)
15762 {
15763 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015764 $Affected = $ContentSpanStart_Affected."[+] affected symbols (".(keys(%SProblems)>$LIMIT?">".$LIMIT:keys(%SProblems)).")".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015765 }
15766 }
15767 return $Affected;
15768}
15769
15770sub cmp_locations($$)
15771{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015772 my ($L1, $L2) = @_;
15773 if($L2=~/\b(retval|this)\b/
15774 and $L1!~/\b(retval|this)\b/ and $L1!~/\-\>/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015775 return 1;
15776 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015777 if($L2=~/\b(retval|this)\b/ and $L2=~/\-\>/
15778 and $L1!~/\b(retval|this)\b/ and $L1=~/\-\>/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015779 return 1;
15780 }
15781 return 0;
15782}
15783
15784sub getAffectDescription($$$$)
15785{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015786 my ($Level, $Symbol, $Kind, $Location) = @_;
15787 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015788 my $PPos = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015789 my @Sentence = ();
15790 $Location=~s/\A(.*)\-\>.+?\Z/$1/;
15791 if($Kind eq "Overridden_Virtual_Method"
15792 or $Kind eq "Overridden_Virtual_Method_B") {
15793 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
15794 }
15795 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15796 {
15797 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
15798 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015799 my $METHOD_TYPE = $CompleteSignature{1}{$Symbol}{"Constructor"}?"constructor":"method";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015800 my $ClassName = $TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015801 if($ClassName eq $Problem{"Type_Name"}) {
15802 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
15803 }
15804 else {
15805 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
15806 }
15807 }
15808 else
15809 {
15810 if($Location=~/retval/)
15811 { # return value
15812 if($Location=~/\-\>/) {
15813 push(@Sentence, "Field \'".$Location."\' in return value");
15814 }
15815 else {
15816 push(@Sentence, "Return value");
15817 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015818 if(my $Init = $Problem{"InitialType_Type"})
15819 {
15820 if($Init eq "Pointer") {
15821 push(@Sentence, "(pointer)");
15822 }
15823 elsif($Init eq "Ref") {
15824 push(@Sentence, "(reference)");
15825 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015826 }
15827 }
15828 elsif($Location=~/this/)
15829 { # "this" pointer
15830 if($Location=~/\-\>/) {
15831 push(@Sentence, "Field \'".$Location."\' in the object of this method");
15832 }
15833 else {
15834 push(@Sentence, "\'this\' pointer");
15835 }
15836 }
15837 else
15838 { # parameters
15839 if($Location=~/\-\>/) {
15840 push(@Sentence, "Field \'".$Location."\' in $PPos parameter");
15841 }
15842 else {
15843 push(@Sentence, "$PPos parameter");
15844 }
15845 if($Problem{"Param_Name"}) {
15846 push(@Sentence, "\'".$Problem{"Param_Name"}."\'");
15847 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015848 if(my $Init = $Problem{"InitialType_Type"})
15849 {
15850 if($Init eq "Pointer") {
15851 push(@Sentence, "(pointer)");
15852 }
15853 elsif($Init eq "Ref") {
15854 push(@Sentence, "(reference)");
15855 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015856 }
15857 }
15858 if($Location eq "this") {
15859 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
15860 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015861 elsif(defined $Problem{"Start_Type_Name"}
15862 and $Problem{"Start_Type_Name"} eq $Problem{"Type_Name"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015863 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
15864 }
15865 else {
15866 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
15867 }
15868 }
15869 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015870 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015871 push(@Sentence, " This is a symbol from an artificial external library that may use the \'$TargetLibraryName\' library and change its ABI after recompiling.");
15872 }
15873 return join(" ", @Sentence);
15874}
15875
15876sub get_XmlSign($$)
15877{
15878 my ($Symbol, $LibVersion) = @_;
15879 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
15880 my $Report = "";
15881 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
15882 {
15883 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015884 my $Type = $Info->{"Param"}{$Pos}{"type"};
15885 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015886 foreach my $Typedef (keys(%ChangedTypedef))
15887 {
15888 my $Base = $Typedef_BaseName{$LibVersion}{$Typedef};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015889 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015890 }
15891 $Report .= " <param pos=\"$Pos\">\n";
15892 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015893 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015894 $Report .= " </param>\n";
15895 }
15896 if(my $Return = $Info->{"Return"})
15897 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015898 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015899 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015900 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015901 $Report .= " </retval>\n";
15902 }
15903 return $Report;
15904}
15905
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015906sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015907{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015908 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015909 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015910 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015911 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015912 my ($SN, $SS, $SV) = separate_symbol($Symbol);
15913 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015914 next;
15915 }
15916 $Report .= " <symbol name=\"$Symbol\">\n";
15917 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015918 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015919 {
15920 if(defined $CompleteSignature{1}{$Symbol}
15921 and defined $CompleteSignature{1}{$Symbol}{"Header"})
15922 {
15923 $P1 = get_XmlSign($Symbol, 1);
15924 $S1 = get_Signature($Symbol, 1);
15925 }
15926 elsif($Symbol=~/\A(_Z|\?)/) {
15927 $S1 = $tr_name{$Symbol};
15928 }
15929 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015930 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015931 {
15932 if(defined $CompleteSignature{2}{$Symbol}
15933 and defined $CompleteSignature{2}{$Symbol}{"Header"})
15934 {
15935 $P2 = get_XmlSign($Symbol, 2);
15936 $S2 = get_Signature($Symbol, 2);
15937 }
15938 elsif($Symbol=~/\A(_Z|\?)/) {
15939 $S2 = $tr_name{$Symbol};
15940 }
15941 }
15942 if($S1)
15943 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015944 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015945 $Report .= $P1;
15946 $Report .= " </old>\n";
15947 }
15948 if($S2 and $S2 ne $S1)
15949 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015950 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015951 $Report .= $P2;
15952 $Report .= " </new>\n";
15953 }
15954 $Report .= " </symbol>\n";
15955 }
15956 $Report .= "</symbols_info>\n";
15957 return $Report;
15958}
15959
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015960sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015961{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015962 my ($Level, $Report) = @_;
15963 if($ReportFormat eq "xml") {
15964 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015965 }
15966 if($StdOut)
15967 { # --stdout option
15968 print STDOUT $Report;
15969 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015970 else
15971 {
15972 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015973 mkpath(get_dirname($RPath));
15974
15975 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
15976 print REPORT $Report;
15977 close(REPORT);
15978
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015979 if($Browse or $OpenReport)
15980 { # open in browser
15981 openReport($RPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015982 if($JoinReport or $DoubleReport)
15983 {
15984 if($Level eq "Binary")
15985 { # wait to open a browser
15986 sleep(1);
15987 }
15988 }
15989 }
15990 }
15991}
15992
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015993sub openReport($)
15994{
15995 my $Path = $_[0];
15996 my $Cmd = "";
15997 if($Browse)
15998 { # user-defined browser
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040015999 $Cmd = $Browse." \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016000 }
16001 if(not $Cmd)
16002 { # default browser
16003 if($OSgroup eq "macos") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040016004 $Cmd = "open \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016005 }
16006 elsif($OSgroup eq "windows") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040016007 $Cmd = "start ".path_format($Path, $OSgroup);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016008 }
16009 else
16010 { # linux, freebsd, solaris
16011 my @Browsers = (
16012 "x-www-browser",
16013 "sensible-browser",
16014 "firefox",
16015 "opera",
16016 "xdg-open",
16017 "lynx",
16018 "links"
16019 );
16020 foreach my $Br (@Browsers)
16021 {
16022 if($Br = get_CmdPath($Br))
16023 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040016024 $Cmd = $Br." \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016025 last;
16026 }
16027 }
16028 }
16029 }
16030 if($Cmd)
16031 {
16032 if($Debug) {
16033 printMsg("INFO", "running $Cmd");
16034 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040016035 if($OSgroup ne "windows"
16036 and $OSgroup ne "macos")
16037 {
16038 if($Cmd!~/lynx|links/) {
16039 $Cmd .= " >\"$TMP_DIR/null\" 2>&1 &";
16040 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016041 }
16042 system($Cmd);
16043 }
16044 else {
16045 printMsg("ERROR", "cannot open report in browser");
16046 }
16047}
16048
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016049sub getReport($)
16050{
16051 my $Level = $_[0];
16052 if($ReportFormat eq "xml")
16053 { # XML
16054
16055 if($Level eq "Join")
16056 {
16057 my $Report = "<reports>\n";
16058 $Report .= getReport("Binary");
16059 $Report .= getReport("Source");
16060 $Report .= "</reports>\n";
16061 return $Report;
16062 }
16063 else
16064 {
16065 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
16066 my ($Summary, $MetaData) = get_Summary($Level);
16067 $Report .= $Summary."\n";
16068 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
16069 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
16070 $Report .= get_Report_SymbolsInfo($Level);
16071 $Report .= "</report>\n";
16072 return $Report;
16073 }
16074 }
16075 else
16076 { # HTML
16077 my $CssStyles = readModule("Styles", "Report.css");
16078 my $JScripts = readModule("Scripts", "Sections.js");
16079 if($Level eq "Join")
16080 {
16081 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
16082 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040016083 my $Title = $TargetLibraryFName.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
16084 my $Keywords = $TargetLibraryFName.", compatibility, API, report";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016085 my $Description = "Compatibility report for the $TargetLibraryFName $TargetComponent between ".$Descriptor{1}{"Version"}." and ".$Descriptor{2}{"Version"}." versions";
16086 my ($BSummary, $BMetaData) = get_Summary("Binary");
16087 my ($SSummary, $SMetaData) = get_Summary("Source");
16088 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>";
16089 $Report .= get_Report_Header("Join")."
16090 <br/><div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016091 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
16092 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016093 </div>";
16094 $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>";
16095 $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 +040016096 $Report .= getReportFooter($TargetLibraryFName, not $JoinReport);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016097 $Report .= "\n<div style='height:999px;'></div>\n</body></html>";
16098 return $Report;
16099 }
16100 else
16101 {
16102 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040016103 my $Title = $TargetLibraryFName.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
16104 my $Keywords = $TargetLibraryFName.", ".lc($Level)." compatibility, API, report";
16105 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 +040016106 if($Level eq "Binary")
16107 {
16108 if(getArch(1) eq getArch(2)
16109 and getArch(1) ne "unknown") {
16110 $Description .= " on ".showArch(getArch(1));
16111 }
16112 }
16113 my $Report = "<!-\- $MetaData -\->\n".composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."\n<body>\n<div><a name='Top'></a>\n";
16114 $Report .= get_Report_Header($Level)."\n".$Summary."\n";
16115 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
16116 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
16117 $Report .= get_SourceInfo();
16118 $Report .= "</div>\n<br/><br/><br/><hr/>\n";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016119 $Report .= getReportFooter($TargetLibraryFName, not $JoinReport);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016120 $Report .= "\n<div style='height:999px;'></div>\n</body></html>";
16121 return $Report;
16122 }
16123 }
16124}
16125
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016126sub getLegend()
16127{
16128 return "<br/>
16129<table class='summary'>
16130<tr>
16131 <td class='new'>added</td>
16132 <td class='passed'>compatible</td>
16133</tr>
16134<tr>
16135 <td class='warning'>warning</td>
16136 <td class='failed'>incompatible</td>
16137</tr></table>\n";
16138}
16139
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016140sub createReport()
16141{
16142 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016143 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016144 writeReport("Join", getReport("Join"));
16145 }
16146 elsif($DoubleReport)
16147 { # default
16148 writeReport("Binary", getReport("Binary"));
16149 writeReport("Source", getReport("Source"));
16150 }
16151 elsif($BinaryOnly)
16152 { # --binary
16153 writeReport("Binary", getReport("Binary"));
16154 }
16155 elsif($SourceOnly)
16156 { # --source
16157 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016158 }
16159}
16160
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016161sub getReportFooter($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016162{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016163 my ($LibName, $Wide) = @_;
16164 my $FooterStyle = $Wide?"width:99%":"width:97%;padding-top:3px";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016165 my $Footer = "<div style='$FooterStyle;font-size:11px;' align='right'><i>Generated on ".(localtime time); # report date
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016166 $Footer .= " for <span style='font-weight:bold'>$LibName</span>"; # tested library/system name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016167 $Footer .= " by <a href='".$HomePage{"Wiki"}."'>ABI Compliance Checker</a>"; # tool name
16168 my $ToolSummary = "<br/>A tool for checking backward compatibility of a C/C++ library API&#160;&#160;";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016169 $Footer .= " $TOOL_VERSION &#160;$ToolSummary</i></div>"; # tool version
16170 return $Footer;
16171}
16172
16173sub get_Report_Problems($$)
16174{
16175 my ($Priority, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016176 my $Report = get_Report_TypeProblems($Priority, $Level);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016177 if(my $SProblems = get_Report_SymbolProblems($Priority, $Level)) {
16178 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016179 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016180 if($Priority eq "Low")
16181 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016182 $Report .= get_Report_ChangedConstants($Level);
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +040016183 if($ReportFormat eq "html")
16184 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016185 if($CheckImpl and $Level eq "Binary") {
16186 $Report .= get_Report_Impl();
16187 }
16188 }
16189 }
16190 if($ReportFormat eq "html")
16191 {
16192 if($Report)
16193 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016194 if($JoinReport)
16195 {
16196 if($Priority eq "Safe") {
16197 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
16198 }
16199 else {
16200 $Report = "<a name=\'".$Priority."_Risk_".$Level."_Problems\'></a>".$Report;
16201 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016202 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016203 else
16204 {
16205 if($Priority eq "Safe") {
16206 $Report = "<a name=\'Other_Changes\'></a>".$Report;
16207 }
16208 else {
16209 $Report = "<a name=\'".$Priority."_Risk_Problems\'></a>".$Report;
16210 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016211 }
16212 }
16213 }
16214 return $Report;
16215}
16216
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016217sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016218{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016219 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
16220 return "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
16221 <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
16222 <head>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016223 <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
16224 <meta name=\"keywords\" content=\"$Keywords\" />
16225 <meta name=\"description\" content=\"$Description\" />
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016226 <title>
16227 $Title
16228 </title>
16229 <style type=\"text/css\">
16230 $Styles
16231 </style>
16232 <script type=\"text/javascript\" language=\"JavaScript\">
16233 <!--
16234 $Scripts
16235 -->
16236 </script>
16237 </head>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016238}
16239
16240sub insertIDs($)
16241{
16242 my $Text = $_[0];
16243 while($Text=~/CONTENT_ID/)
16244 {
16245 if(int($Content_Counter)%2) {
16246 $ContentID -= 1;
16247 }
16248 $Text=~s/CONTENT_ID/c_$ContentID/;
16249 $ContentID += 1;
16250 $Content_Counter += 1;
16251 }
16252 return $Text;
16253}
16254
16255sub checkPreprocessedUnit($)
16256{
16257 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040016258 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016259 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016260 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016261
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040016262 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016263 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040016264 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016265 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040016266 chomp($Line);
16267 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016268 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040016269 $CurHeader = path_format($1, $OSgroup);
16270 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016271 $CurClass = "";
16272
16273 if(index($CurHeader, $TMP_DIR)==0) {
16274 next;
16275 }
16276
16277 if($ExtraInfo)
16278 {
16279 if(substr($CurHeaderName, 0, 1) ne "<")
16280 { # skip <built-in>, <command-line>, etc.
16281 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
16282 }
16283 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016284 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016285 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040016286 {
16287 if(not $Include_Neighbors{$Version}{$CurHeaderName}
16288 and not $Registered_Headers{$Version}{$CurHeader})
16289 { # not a target
16290 next;
16291 }
16292 if(not is_target_header($CurHeaderName, 1)
16293 and not is_target_header($CurHeaderName, 2))
16294 { # user-defined header
16295 next;
16296 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040016297 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040016298
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016299 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040016300 {
16301 my ($Name, $Value) = ($1, $2);
16302 if(not $Constants{$Version}{$Name}{"Access"})
16303 {
16304 $Constants{$Version}{$Name}{"Access"} = "public";
16305 $Constants{$Version}{$Name}{"Value"} = $Value;
16306 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
16307 }
16308 }
16309 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
16310 $Constants{$Version}{$1}{"Access"} = "private";
16311 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016312 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016313 else
16314 {
16315 if(defined $ExtraDump)
16316 {
16317 if($Line=~/(\w+)\s*\(/)
16318 { # functions
16319 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
16320 }
16321 #elsif($Line=~/(\w+)\s*;/)
16322 #{ # data
16323 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
16324 #}
16325 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
16326 $CurClass = $2;
16327 }
16328 }
16329 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016330 }
16331 close(PREPROC);
16332 foreach my $Constant (keys(%{$Constants{$Version}}))
16333 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016334 if($Constants{$Version}{$Constant}{"Access"} eq "private")
16335 {
16336 delete($Constants{$Version}{$Constant});
16337 next;
16338 }
16339 if(not $ExtraDump and ($Constant=~/_h\Z/i or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
16340 { # skip
16341 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016342 }
16343 else {
16344 delete($Constants{$Version}{$Constant}{"Access"});
16345 }
16346 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040016347 if($Debug)
16348 {
16349 mkpath($DEBUG_PATH{$Version});
16350 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
16351 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016352}
16353
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016354sub uncoverConstant($$)
16355{
16356 my ($LibVersion, $Constant) = @_;
16357 return "" if(not $LibVersion or not $Constant);
16358 return $Constant if(isCyclical(\@RecurConstant, $Constant));
16359 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
16360 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
16361 }
16362 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
16363 if(defined $Value)
16364 {
16365 if($Value=~/\A[A-Z0-9_]+\Z/ and $Value=~/[A-Z]/)
16366 {
16367 push(@RecurConstant, $Constant);
16368 my $Uncovered = uncoverConstant($LibVersion, $Value);
16369 if($Uncovered ne "") {
16370 $Value = $Uncovered;
16371 }
16372 pop(@RecurConstant);
16373 }
16374 # FIXME: uncover $Value using all the enum constants
16375 # USECASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
16376 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
16377 }
16378 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
16379}
16380
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016381my %IgnoreConstant = map {$_=>1} (
16382 "VERSION",
16383 "VERSIONCODE",
16384 "VERNUM",
16385 "VERS_INFO",
16386 "PATCHLEVEL",
16387 "INSTALLPREFIX",
16388 "VBUILD",
16389 "VPATCH",
16390 "VMINOR",
16391 "BUILD_STRING",
16392 "BUILD_TIME",
16393 "PACKAGE_STRING",
16394 "PRODUCTION",
16395 "CONFIGURE_COMMAND",
16396 "INSTALLDIR",
16397 "BINDIR",
16398 "CONFIG_FILE_PATH",
16399 "DATADIR",
16400 "EXTENSION_DIR",
16401 "INCLUDE_PATH",
16402 "LIBDIR",
16403 "LOCALSTATEDIR",
16404 "SBINDIR",
16405 "SYSCONFDIR",
16406 "RELEASE",
16407 "SOURCE_ID",
16408 "SUBMINOR",
16409 "MINOR",
16410 "MINNOR",
16411 "MINORVERSION",
16412 "MAJOR",
16413 "MAJORVERSION",
16414 "MICRO",
16415 "MICROVERSION",
16416 "BINARY_AGE",
16417 "INTERFACE_AGE",
16418 "CORE_ABI",
16419 "PATCH",
16420 "COPYRIGHT",
16421 "TIMESTAMP",
16422 "REVISION",
16423 "PACKAGE_TAG",
16424 "PACKAGEDATE",
16425 "NUMVERSION",
16426 "Release",
16427 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016428);
16429
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016430sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016431{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016432 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016433 foreach my $Constant (keys(%{$Constants{1}}))
16434 {
16435 if($SkipConstants{1}{$Constant})
16436 { # skipped by the user
16437 next;
16438 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016439 if(not defined $Constants{2}{$Constant}{"Value"}
16440 or $Constants{2}{$Constant}{"Value"} eq "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016441 { # empty value
16442 next;
16443 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016444 my $Header = $Constants{1}{$Constant}{"Header"};
16445 if(not is_target_header($Header, 1)
16446 and not is_target_header($Header, 2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016447 { # user-defined header
16448 next;
16449 }
16450 my ($Old_Value, $New_Value, $Old_Value_Pure, $New_Value_Pure);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016451 $Old_Value = $Old_Value_Pure = uncoverConstant(1, $Constant);
16452 $New_Value = $New_Value_Pure = uncoverConstant(2, $Constant);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016453 $Old_Value_Pure=~s/(\W)\s+/$1/g;
16454 $Old_Value_Pure=~s/\s+(\W)/$1/g;
16455 $New_Value_Pure=~s/(\W)\s+/$1/g;
16456 $New_Value_Pure=~s/\s+(\W)/$1/g;
16457 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
16458 if($New_Value_Pure ne $Old_Value_Pure)
16459 { # different values
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016460 if($Level eq "Binary")
16461 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016462 foreach (keys(%IgnoreConstant))
16463 {
16464 if($Constant=~/(\A|_)$_(_|\Z)/)
16465 { # ignore library version
16466 next;
16467 }
16468 if(/\A[A-Z].*[a-z]\Z/)
16469 {
16470 if($Constant=~/(\A|[a-z])$_([A-Z]|\Z)/)
16471 { # ignore library version
16472 next;
16473 }
16474 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016475 }
16476 if($Constant=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
16477 { # ignore library version
16478 next;
16479 }
16480 if($Old_Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Old_Value=~/[\/\\]\w+[\/\\]\w+/)
16481 { # ignoring path defines:
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016482 # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016483 next;
16484 }
16485 if($Old_Value=~/\A\(*[a-z_]+(\s+|\|)/i)
16486 { # ignore source defines:
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016487 # static int gcry_pth_init ( void) { return ...
16488 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
16489 next;
16490 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016491 if($Old_Value=~/\(/i and $Old_Value!~/\A[\"\']/i)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016492 { # ignore source defines:
16493 # foo(p)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016494 next;
16495 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016496 }
16497 if(convert_integer($Old_Value) eq convert_integer($New_Value))
16498 { # 0x0001 and 0x1, 0x1 and 1 equal constants
16499 next;
16500 }
16501 if($Old_Value eq "0" and $New_Value eq "NULL")
16502 { # 0 => NULL
16503 next;
16504 }
16505 if($Old_Value eq "NULL" and $New_Value eq "0")
16506 { # NULL => 0
16507 next;
16508 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016509 %{$ProblemsWithConstants{$Level}{$Constant}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016510 "Target"=>$Constant,
16511 "Old_Value"=>$Old_Value,
16512 "New_Value"=>$New_Value );
16513 }
16514 }
16515}
16516
16517sub convert_integer($)
16518{
16519 my $Value = $_[0];
16520 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016521 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016522 return hex($Value);
16523 }
16524 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016525 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016526 return oct($Value);
16527 }
16528 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016529 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016530 return oct($Value);
16531 }
16532 else {
16533 return $Value;
16534 }
16535}
16536
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016537sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016538{
16539 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016540 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016541 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016542 {
16543 if($LibVersion==1)
16544 {
16545 printMsg("WARNING", "checking headers only");
16546 $CheckHeadersOnly = 1;
16547 }
16548 else {
16549 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
16550 }
16551 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040016552
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040016553 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016554 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016555 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040016556
16557 if($CheckUndefined)
16558 {
16559 my %UndefinedLibs = ();
16560
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016561 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
16562
16563 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040016564 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016565 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040016566 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016567 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040016568 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016569 if(not $Symbol_Library{$LibVersion}{$Symbol}
16570 and not $DepSymbol_Library{$LibVersion}{$Symbol})
16571 {
16572 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
16573 $UndefinedLibs{$Path} = 1;
16574 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040016575 }
16576 }
16577 }
16578 }
16579 if($ExtraInfo)
16580 { # extra information for other tools
16581 if(my @Paths = keys(%UndefinedLibs))
16582 {
16583 my $LibString = "";
16584 foreach (@Paths)
16585 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016586 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040016587 my ($Dir, $Name) = separate_path($_);
16588
16589 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016590 $LibString .= " -L".esc($Dir);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040016591 }
16592
16593 $Name = parse_libname($Name, "name", $OStarget);
16594 $Name=~s/\Alib//;
16595
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016596 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040016597 }
16598 writeFile($ExtraInfo."/libs-string", $LibString);
16599 }
16600 }
16601 }
16602
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016603 if($ExtraInfo) {
16604 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
16605 }
16606
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016607 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016608 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016609 if($#LibPaths!=-1)
16610 {
16611 if(not keys(%{$Symbol_Library{$LibVersion}}))
16612 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016613 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016614 printMsg("WARNING", "checking headers only");
16615 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016616 }
16617 }
16618 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016619
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040016620 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016621 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016622}
16623
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040016624my %Prefix_Lib_Map=(
16625 # symbols for autodetecting library dependencies (by prefix)
16626 "pthread_" => ["libpthread"],
16627 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
16628 "cairo_" => ["libcairo"],
16629 "gtk_" => ["libgtk-x11-2.0"],
16630 "atk_" => ["libatk-1.0"],
16631 "gdk_" => ["libgdk-x11-2.0"],
16632 "gl" => ["libGL"],
16633 "glu" => ["libGLU"],
16634 "popt" => ["libpopt"],
16635 "Py" => ["libpython"],
16636 "jpeg_" => ["libjpeg"],
16637 "BZ2_" => ["libbz2"],
16638 "Fc" => ["libfontconfig"],
16639 "Xft" => ["libXft"],
16640 "SSL_" => ["libssl"],
16641 "sem_" => ["libpthread"],
16642 "snd_" => ["libasound"],
16643 "art_" => ["libart_lgpl_2"],
16644 "dbus_g" => ["libdbus-glib-1"],
16645 "GOMP_" => ["libgomp"],
16646 "omp_" => ["libgomp"],
16647 "cms" => ["liblcms"]
16648);
16649
16650my %Pattern_Lib_Map=(
16651 "SL[a-z]" => ["libslang"]
16652);
16653
16654my %Symbol_Lib_Map=(
16655 # symbols for autodetecting library dependencies (by name)
16656 "pow" => "libm",
16657 "fmod" => "libm",
16658 "sin" => "libm",
16659 "floor" => "libm",
16660 "cos" => "libm",
16661 "dlopen" => "libdl",
16662 "deflate" => "libz",
16663 "inflate" => "libz",
16664 "move_panel" => "libpanel",
16665 "XOpenDisplay" => "libX11",
16666 "resize_term" => "libncurses",
16667 "clock_gettime" => "librt"
16668);
16669
16670sub find_SymbolLibs($$)
16671{
16672 my ($LibVersion, $Symbol) = @_;
16673
16674 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
16675 { # debug symbols
16676 return ();
16677 }
16678
16679 my %Paths = ();
16680
16681 if(my $LibName = $Symbol_Lib_Map{$Symbol})
16682 {
16683 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
16684 $Paths{$Path} = 1;
16685 }
16686 }
16687
16688 if(my $SymbolPrefix = getPrefix($Symbol))
16689 {
16690 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
16691 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
16692 }
16693
16694 if(not keys(%Paths))
16695 {
16696 if(defined $Prefix_Lib_Map{$SymbolPrefix})
16697 {
16698 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
16699 {
16700 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
16701 $Paths{$Path} = 1;
16702 }
16703 }
16704 }
16705 }
16706
16707 if(not keys(%Paths))
16708 {
16709 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
16710 {
16711 if($Symbol=~/\A$Prefix/)
16712 {
16713 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
16714 {
16715 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
16716 $Paths{$Path} = 1;
16717 }
16718 }
16719 }
16720 }
16721 }
16722
16723 if(not keys(%Paths))
16724 {
16725 if($SymbolPrefix)
16726 { # try to find a library by symbol prefix
16727 if($SymbolPrefix eq "inotify" and
16728 index($Symbol, "\@GLIBC")!=-1)
16729 {
16730 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
16731 $Paths{$Path} = 1;
16732 }
16733 }
16734 else
16735 {
16736 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
16737 $Paths{$Path} = 1;
16738 }
16739 }
16740 }
16741 }
16742
16743 if(my @Paths = keys(%Paths)) {
16744 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
16745 }
16746 }
16747 return keys(%Paths);
16748}
16749
16750sub get_LibPath_Prefix($$)
16751{
16752 my ($LibVersion, $Prefix) = @_;
16753
16754 $Prefix = lc($Prefix);
16755 $Prefix=~s/[_]+\Z//g;
16756
16757 foreach ("-2", "2", "-1", "1", "")
16758 { # libgnome-2.so
16759 # libxml2.so
16760 # libdbus-1.so
16761 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
16762 return $Path;
16763 }
16764 }
16765 return "";
16766}
16767
16768sub getPrefix($)
16769{
16770 my $Str = $_[0];
16771 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
16772 { # XmuValidArea: Xmu
16773 return $1;
16774 }
16775 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
16776 { # snfReadFont: snf
16777 return $1;
16778 }
16779 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
16780 { # XRRTimes: XRR
16781 return $1;
16782 }
16783 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
16784 { # H5HF_delete: H5
16785 return $1;
16786 }
16787 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
16788 { # alarm_event_add: alarm_
16789 return $1;
16790 }
16791 elsif($Str=~/\A(([a-z])\2{1,})/i)
16792 { # ffopen
16793 return $1;
16794 }
16795 return "";
16796}
16797
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016798sub getSymbolSize($$)
16799{ # size from the shared library
16800 my ($Symbol, $LibVersion) = @_;
16801 return 0 if(not $Symbol);
16802 if(defined $Symbol_Library{$LibVersion}{$Symbol}
16803 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
16804 {
16805 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
16806 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
16807 {
16808 if($Size<0) {
16809 return -$Size;
16810 }
16811 }
16812 }
16813 return 0;
16814}
16815
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040016816sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016817{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
16818 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040016819 my ($Name, $Type) = @_;
16820
16821 # single
16822 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016823 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016824 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040016825 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016826 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040016827
16828 # double
16829 if($Name=~/$DEFAULT_STD_PARMS/)
16830 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040016831 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040016832 {
16833 my ($ShortName, $FuncParams) = split_Signature($Name);
16834
16835 foreach my $FParam (separate_Params($FuncParams, 0, 0))
16836 {
16837 if(index($FParam, "<")!=-1)
16838 {
16839 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
16840 my $FParam_N = canonifyName($FParam, "T");
16841 if($FParam_N ne $FParam) {
16842 $Name=~s/\Q$FParam\E/$FParam_N/g;
16843 }
16844 }
16845 }
16846 }
16847 elsif($Type eq "T")
16848 {
16849 my ($ShortTmpl, $TmplParams) = template_Base($Name);
16850
16851 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040016852 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040016853 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040016854 my $FParam = $TParams[0];
16855 foreach my $Pos (1 .. $#TParams)
16856 {
16857 my $TParam = $TParams[$Pos];
16858 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
16859 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
16860 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040016861 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040016862 }
16863 }
16864 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040016865 if($Type eq "S") {
16866 return formatName($Name, "S");
16867 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016868 return $Name;
16869}
16870
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016871sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016872{
16873 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016874 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016875 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016876 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016877 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016878 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016879 next if($tr_name{$Symbol});
16880 $Symbol=~s/[\@\$]+(.*)\Z//;
16881 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016882 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040016883 elsif(index($Symbol, "?")==0)
16884 {
16885 next if($tr_name{$Symbol});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016886 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016887 }
16888 else
16889 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016890 $tr_name{$Symbol} = $Symbol;
16891 $mangled_name_gcc{$Symbol} = $Symbol;
16892 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016893 }
16894 }
16895 if($#MnglNames1 > -1)
16896 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016897 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016898 foreach my $MnglName (@MnglNames1)
16899 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016900 if(my $Unmangled = pop(@UnmangledNames))
16901 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040016902 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016903 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
16904 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
16905 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016906 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016907 and $tr_name{$MnglName}=~/vtable for (.+)/)
16908 { # bind class name and v-table symbol
16909 my $ClassName = $1;
16910 $ClassVTable{$ClassName} = $MnglName;
16911 $VTableClass{$MnglName} = $ClassName;
16912 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016913 }
16914 }
16915 }
16916 if($#MnglNames2 > -1)
16917 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016918 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016919 foreach my $MnglName (@MnglNames2)
16920 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016921 if(my $Unmangled = pop(@UnmangledNames))
16922 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016923 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016924 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
16925 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016926 }
16927 }
16928 return \%tr_name;
16929}
16930
16931sub link_symbol($$$)
16932{
16933 my ($Symbol, $RunWith, $Deps) = @_;
16934 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
16935 return 1;
16936 }
16937 if($Deps eq "+Deps")
16938 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016939 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016940 return 1;
16941 }
16942 }
16943 return 0;
16944}
16945
16946sub link_symbol_internal($$$)
16947{
16948 my ($Symbol, $RunWith, $Where) = @_;
16949 return 0 if(not $Where or not $Symbol);
16950 if($Where->{$RunWith}{$Symbol})
16951 { # the exact match by symbol name
16952 return 1;
16953 }
16954 if(my $VSym = $SymVer{$RunWith}{$Symbol})
16955 { # indirect symbol version, i.e.
16956 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016957 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016958 if($Where->{$RunWith}{$VSym}) {
16959 return 1;
16960 }
16961 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016962 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016963 if($Sym and $Ver)
16964 { # search for the symbol with the same version
16965 # or without version
16966 if($Where->{$RunWith}{$Sym})
16967 { # old: foo@v|foo@@v
16968 # new: foo
16969 return 1;
16970 }
16971 if($Where->{$RunWith}{$Sym."\@".$Ver})
16972 { # old: foo|foo@@v
16973 # new: foo@v
16974 return 1;
16975 }
16976 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
16977 { # old: foo|foo@v
16978 # new: foo@@v
16979 return 1;
16980 }
16981 }
16982 return 0;
16983}
16984
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016985sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016986{
16987 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016988 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016989 my @Imported = ();
16990 if($OSgroup eq "macos")
16991 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040016992 my $NM = get_CmdPath("nm");
16993 if(not $NM) {
16994 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016995 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040016996 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016997 while(<APP>)
16998 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040016999 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017000 push(@Imported, $1);
17001 }
17002 }
17003 close(APP);
17004 }
17005 elsif($OSgroup eq "windows")
17006 {
17007 my $DumpBinCmd = get_CmdPath("dumpbin");
17008 if(not $DumpBinCmd) {
17009 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
17010 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017011 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017012 while(<APP>)
17013 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017014 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
17015 push(@Imported, $1);
17016 }
17017 }
17018 close(APP);
17019 }
17020 else
17021 {
17022 my $ReadelfCmd = get_CmdPath("readelf");
17023 if(not $ReadelfCmd) {
17024 exitStatus("Not_Found", "can't find \"readelf\"");
17025 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017026 open(APP, "$ReadelfCmd -WhlSsdA \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017027 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017028 while(<APP>)
17029 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017030 if(defined $symtab)
17031 { # do nothing with symtab
17032 if(index($_, "'.dynsym'")!=-1)
17033 { # dynamic table
17034 $symtab = undef;
17035 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017036 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017037 elsif(index($_, "'.symtab'")!=-1)
17038 { # symbol table
17039 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017040 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017041 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017042 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017043 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
17044 if($Ndx eq "UND")
17045 { # only imported symbols
17046 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017047 }
17048 }
17049 }
17050 close(APP);
17051 }
17052 return @Imported;
17053}
17054
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017055my %ELF_BIND = map {$_=>1} (
17056 "WEAK",
17057 "GLOBAL"
17058);
17059
17060my %ELF_TYPE = map {$_=>1} (
17061 "FUNC",
17062 "IFUNC",
17063 "OBJECT",
17064 "COMMON"
17065);
17066
17067my %ELF_VIS = map {$_=>1} (
17068 "DEFAULT",
17069 "PROTECTED"
17070);
17071
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017072sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017073{ # read the line of 'readelf' output corresponding to the symbol
17074 my @Info = split(/\s+/, $_[0]);
17075 # Num: Value Size Type Bind Vis Ndx Name
17076 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
17077 shift(@Info); # spaces
17078 shift(@Info); # num
17079 if($#Info!=6)
17080 { # other lines
17081 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017082 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017083 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017084 return () if(not defined $ELF_BIND{$Info[3]});
17085 return () if(not defined $ELF_VIS{$Info[4]});
17086 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
17087 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
17088 return ();
17089 }
17090 if($OStarget eq "symbian")
17091 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
17092 if(index($Info[6], "_._.absent_export_")!=-1)
17093 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
17094 return ();
17095 }
17096 $Info[6]=~s/\@.+//g; # remove version
17097 }
17098 if(index($Info[2], "0x") == 0)
17099 { # size == 0x3d158
17100 $Info[2] = hex($Info[2]);
17101 }
17102 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017103}
17104
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017105sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017106{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017107 my ($LibVersion, $Name) = @_;
17108 return "" if(not $LibVersion or not $Name);
17109 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
17110 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017111 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017112 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
17113}
17114
17115sub get_LibPath_I($$)
17116{
17117 my ($LibVersion, $Name) = @_;
17118 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017119 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017120 if(-f $Name)
17121 { # absolute path
17122 return $Name;
17123 }
17124 else
17125 { # broken
17126 return "";
17127 }
17128 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017129 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017130 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017131 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017132 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017133 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017134 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017135 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017136 }
17137 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
17138 { # ldconfig default paths
17139 return $DefaultPath;
17140 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017141 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017142 { # search in default linker directories
17143 # and then in all system paths
17144 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017145 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017146 }
17147 }
17148 detectSystemObjects() if(not keys(%SystemObjects));
17149 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
17150 return $AllObjects[0];
17151 }
17152 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
17153 {
17154 if($ShortName ne $Name)
17155 { # FIXME: check this case
17156 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
17157 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017158 }
17159 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017160 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017161 # can't find
17162 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017163}
17164
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017165sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017166{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017167 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
17168 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017169
17170 my $Real_Path = realpath($Lib_Path);
17171
17172 if(not $Real_Path)
17173 { # broken link
17174 return ();
17175 }
17176
17177 my $Lib_Name = get_filename($Real_Path);
17178
17179 if($ExtraInfo) {
17180 $KnownLibs{$Real_Path} = 1;
17181 }
17182
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017183 if($IsNeededLib)
17184 {
17185 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
17186 return ();
17187 }
17188 }
17189 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017190 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017191
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017192 if($CheckImpl)
17193 {
17194 if(not $IsNeededLib) {
17195 getImplementations($LibVersion, $Lib_Path);
17196 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017197 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017198
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017199 push(@RecurLib, $Lib_Name);
17200 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040017201 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
17202
17203 if(not $IsNeededLib)
17204 { # special cases: libstdc++ and libc
17205 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
17206 {
17207 if($ShortName eq "libstdc++")
17208 { # libstdc++.so.6
17209 $STDCXX_TESTING = 1;
17210 }
17211 elsif($ShortName eq "libc")
17212 { # libc-2.11.3.so
17213 $GLIBC_TESTING = 1;
17214 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017215 }
17216 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017217 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017218 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017219 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017220 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017221 mkpath(get_dirname($DebugPath));
17222 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017223 if($OStarget eq "macos")
17224 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017225 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017226 if(not $NM) {
17227 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017228 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017229 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017230 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017231 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017232 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017233 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017234 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017235 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017236 else
17237 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017238 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017239 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017240 while(<LIB>)
17241 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017242 if($CheckUndefined)
17243 {
17244 if(not $IsNeededLib)
17245 {
17246 if(/ U _([\w\$]+)\s*\Z/)
17247 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017248 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017249 next;
17250 }
17251 }
17252 }
17253
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017254 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017255 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017256 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017257 if($IsNeededLib)
17258 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040017259 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017260 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017261 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
17262 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017263 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017264 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017265 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017266 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017267 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
17268 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017269 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
17270 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017271 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017272 setLanguage($LibVersion, "C++");
17273 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017274 }
17275 if($CheckObjectsOnly
17276 and $LibVersion==1) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017277 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017278 }
17279 }
17280 }
17281 }
17282 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017283
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017284 if($Deps)
17285 {
17286 if($LIB_TYPE eq "dynamic")
17287 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017288
17289 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017290 if(not $OtoolCmd) {
17291 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017292 }
17293
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017294 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
17295 while(<LIB>)
17296 {
17297 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
17298 and $1 ne $Lib_Path) {
17299 $NeededLib{$1} = 1;
17300 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017301 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017302 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017303 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017304 }
17305 }
17306 elsif($OStarget eq "windows")
17307 { # Windows *.dll, *.lib
17308 my $DumpBinCmd = get_CmdPath("dumpbin");
17309 if(not $DumpBinCmd) {
17310 exitStatus("Not_Found", "can't find \"dumpbin\"");
17311 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017312 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017313 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017314 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017315 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017316 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017317 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017318 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017319 else
17320 { # write to pipe
17321 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017322 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017323 while(<LIB>)
17324 { # 1197 4AC 0000A620 SetThreadStackGuarantee
17325 # 1198 4AD SetThreadToken (forwarded to ...)
17326 # 3368 _o2i_ECPublicKey
17327 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*\Z/i
17328 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
17329 or /\A\s*\d+\s+_([\w\?\@]+)\s*\Z/)
17330 { # dynamic, static and forwarded symbols
17331 my $realname = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017332 if($IsNeededLib)
17333 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040017334 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017335 {
17336 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
17337 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
17338 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017339 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017340 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017341 {
17342 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
17343 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017344 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
17345 {
17346 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
17347 setLanguage($LibVersion, "C++");
17348 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017349 }
17350 if($CheckObjectsOnly
17351 and $LibVersion==1) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017352 $CheckedSymbols{"Binary"}{$realname} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017353 }
17354 }
17355 }
17356 }
17357 close(LIB);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017358 if($Deps)
17359 {
17360 if($LIB_TYPE eq "dynamic")
17361 { # dependencies
17362 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
17363 while(<LIB>)
17364 {
17365 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
17366 and $1 ne $Lib_Path) {
17367 $NeededLib{path_format($1, $OSgroup)} = 1;
17368 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017369 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017370 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017371 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017372 }
17373 }
17374 else
17375 { # Unix; *.so, *.a
17376 # Symbian: *.dso, *.lib
17377 my $ReadelfCmd = get_CmdPath("readelf");
17378 if(not $ReadelfCmd) {
17379 exitStatus("Not_Found", "can't find \"readelf\"");
17380 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017381 $ReadelfCmd .= " -WhlSsdA \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
17382 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017383 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017384 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017385 system($ReadelfCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017386 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017387 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017388 else
17389 { # write to pipe
17390 open(LIB, $ReadelfCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017391 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017392 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017393 while(<LIB>)
17394 {
17395 if($LIB_TYPE eq "dynamic")
17396 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017397 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017398 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017399 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017400 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017401 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017402 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017403 # do nothing with symtab
17404 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017405 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017406 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017407 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017408 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017409 next;
17410 }
17411 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017412 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017413 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017414 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017415 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017416 if($CheckUndefined)
17417 {
17418 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017419 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017420 }
17421 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017422 next;
17423 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017424 if($Bind eq "WEAK"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017425 and $Weak eq "-Weak")
17426 { # skip WEAK symbols
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017427 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017428 next;
17429 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017430 my $Short = $Symbol;
17431 $Short=~s/\@.+//g;
17432 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017433 { # global data
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017434 $GlobalDataObject{$LibVersion}{$Symbol} = 1;
17435 $GlobalDataObject{$LibVersion}{$Short} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017436 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017437 if($IsNeededLib)
17438 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040017439 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017440 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017441 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
17442 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017443 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017444 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017445 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017446 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017447 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
17448 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
17449 if($Vers)
17450 {
17451 if($LIB_EXT eq "so")
17452 { # value
17453 $Interface_Value{$LibVersion}{$Symbol} = $Value;
17454 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
17455 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017456 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017457 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
17458 {
17459 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
17460 setLanguage($LibVersion, "C++");
17461 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017462 }
17463 if($CheckObjectsOnly
17464 and $LibVersion==1) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017465 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017466 }
17467 }
17468 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017469 elsif($LIB_TYPE eq "dynamic")
17470 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017471 if($Deps)
17472 {
17473 if(/NEEDED.+\[([^\[\]]+)\]/)
17474 { # dependencies:
17475 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
17476 $NeededLib{$1} = 1;
17477 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017478 }
17479 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017480 }
17481 close(LIB);
17482 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017483 if($Vers)
17484 {
17485 if(not $IsNeededLib and $LIB_EXT eq "so")
17486 { # get symbol versions
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017487 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017488 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017489 next if(index($Symbol,"\@")==-1);
17490 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017491 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017492 my $Interface_SymName = "";
17493 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017494 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017495 if($Symbol_SameValue ne $Symbol
17496 and index($Symbol_SameValue,"\@")==-1)
17497 {
17498 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
17499 $Interface_SymName = $Symbol_SameValue;
17500 last;
17501 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017502 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017503 if(not $Interface_SymName)
17504 {
17505 if($Symbol=~/\A([^\@\$\?]*)[\@\$]+([^\@\$]*)\Z/
17506 and not $SymVer{$LibVersion}{$1}) {
17507 $SymVer{$LibVersion}{$1} = $Symbol;
17508 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017509 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017510 }
17511 }
17512 }
17513 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017514 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017515 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017516 foreach my $DyLib (sort keys(%NeededLib))
17517 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017518 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
17519 {
17520 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
17521 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
17522 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017523 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017524 }
17525 }
17526 pop(@RecurLib);
17527 return $Library_Symbol{$LibVersion};
17528}
17529
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017530sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017531{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017532 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017533 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017534 return keys(%Prefixes);
17535}
17536
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017537sub get_prefixes_I($$)
17538{
17539 foreach my $P (@{$_[0]})
17540 {
17541 my @Parts = reverse(split(/[\/\\]+/, $P));
17542 my $Name = $Parts[0];
17543 foreach (1 .. $#Parts)
17544 {
17545 $_[1]->{$Name}{$P} = 1;
17546 last if($_>4 or $Parts[$_] eq "include");
17547 $Name = $Parts[$_].$SLASH.$Name;
17548 }
17549 }
17550}
17551
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017552sub detectSystemHeaders()
17553{
17554 my @SysHeaders = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017555 foreach my $DevelPath (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017556 {
17557 next if(not -d $DevelPath);
17558 # search for all header files in the /usr/include
17559 # with or without extension (ncurses.h, QtCore, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017560 @SysHeaders = (@SysHeaders, cmd_find($DevelPath,"f"));
17561 foreach my $Link (cmd_find($DevelPath,"l"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017562 { # add symbolic links
17563 if(-f $Link) {
17564 push(@SysHeaders, $Link);
17565 }
17566 }
17567 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017568 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017569 { # search for config headers in the /usr/lib
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017570 next if(not -d $DevelPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017571 foreach (cmd_find($DevelPath,"f"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017572 {
17573 if(not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs)/)
17574 {
17575 if(/\.h\Z|\/include\//) {
17576 push(@SysHeaders, $_);
17577 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017578 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017579 }
17580 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017581 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017582}
17583
17584sub detectSystemObjects()
17585{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017586 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017587 {
17588 next if(not -d $DevelPath);
17589 foreach my $Path (find_libs($DevelPath,"",""))
17590 { # search for shared libraries in the /usr/lib (including symbolic links)
17591 $SystemObjects{parse_libname(get_filename($Path), "name+ext", $OStarget)}{$Path}=1;
17592 }
17593 }
17594}
17595
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017596sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017597{
17598 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017599 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017600 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
17601 {
17602 if(not -e $Dest) {
17603 exitStatus("Access_Error", "can't access \'$Dest\'");
17604 }
17605 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
17606 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017607 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017608 }
17609 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017610 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017611}
17612
17613sub skip_lib($$)
17614{
17615 my ($Path, $LibVersion) = @_;
17616 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017617 my $Name = get_filename($Path);
17618 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017619 return 1;
17620 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017621 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017622 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
17623 return 1;
17624 }
17625 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
17626 {
17627 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
17628 return 1;
17629 }
17630 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017631 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017632 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017633 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017634 return 1;
17635 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017636 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017637 return 1;
17638 }
17639 }
17640 return 0;
17641}
17642
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017643sub skipHeader($$)
17644{
17645 my ($Path, $LibVersion) = @_;
17646 return 1 if(not $Path or not $LibVersion);
17647 if(not keys(%{$SkipHeaders{$LibVersion}})) {
17648 return 0;
17649 }
17650 if(defined $Cache{"skipHeader"}{$Path}) {
17651 return $Cache{"skipHeader"}{$Path};
17652 }
17653 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
17654}
17655
17656sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017657{ # returns:
17658 # 1 - if header should NOT be included and checked
17659 # 2 - if header should NOT be included, but should be checked
17660 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017661 my $Name = get_filename($Path);
17662 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017663 return $Kind;
17664 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017665 foreach my $D (keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017666 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017667 if(index($Path, $D)!=-1)
17668 {
17669 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
17670 return $SkipHeaders{$LibVersion}{"Path"}{$D};
17671 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017672 }
17673 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017674 foreach my $P (keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017675 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017676 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
17677 {
17678 if($Name=~/$P/) {
17679 return $Kind;
17680 }
17681 if($P=~/[\/\\]/ and $Path=~/$P/) {
17682 return $Kind;
17683 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017684 }
17685 }
17686 return 0;
17687}
17688
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017689sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017690{
17691 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017692 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017693 { # system directory
17694 return;
17695 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017696 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017697 { # already registered
17698 return;
17699 }
17700 foreach my $Path (find_libs($Dir,"",1))
17701 {
17702 next if(ignore_path($Path));
17703 next if(skip_lib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017704 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017705 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017706 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
17707}
17708
17709sub registerObject($$)
17710{
17711 my ($Path, $LibVersion) = @_;
17712 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017713 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Andrey Ponomarenko27681702012-11-12 16:33:39 +040017714 if($OSgroup=~/linux|bsd/i)
17715 {
17716 if(my $SONAME = getSONAME($Path)) {
17717 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
17718 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017719 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040017720 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
17721 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017722 }
17723}
17724
17725sub getSONAME($)
17726{
17727 my $Path = $_[0];
17728 return if(not $Path);
17729 if(defined $Cache{"getSONAME"}{$Path}) {
17730 return $Cache{"getSONAME"}{$Path};
17731 }
17732 my $ObjdumpCmd = get_CmdPath("objdump");
17733 if(not $ObjdumpCmd) {
17734 exitStatus("Not_Found", "can't find \"objdump\"");
17735 }
17736 my $SonameCmd = "$ObjdumpCmd -x $Path 2>$TMP_DIR/null";
17737 if($OSgroup eq "windows") {
17738 $SonameCmd .= " | find \"SONAME\"";
17739 }
17740 else {
17741 $SonameCmd .= " | grep SONAME";
17742 }
17743 if(my $SonameInfo = `$SonameCmd`) {
17744 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
17745 return ($Cache{"getSONAME"}{$Path} = $1);
17746 }
17747 }
17748 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017749}
17750
17751sub getSOPaths_Dest($$)
17752{
17753 my ($Dest, $LibVersion) = @_;
17754 if(skip_lib($Dest, $LibVersion)) {
17755 return ();
17756 }
17757 if(-f $Dest)
17758 {
17759 if(not parse_libname($Dest, "name", $OStarget)) {
17760 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
17761 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017762 registerObject($Dest, $LibVersion);
17763 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017764 return ($Dest);
17765 }
17766 elsif(-d $Dest)
17767 {
17768 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017769 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017770 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017771 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
17772 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017773 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017774 { # all files and symlinks that match the name of a library
17775 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
17776 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017777 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017778 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017779 }
17780 }
17781 }
17782 else
17783 { # search for all files and symlinks
17784 foreach my $Path (find_libs($Dest,"",""))
17785 {
17786 next if(ignore_path($Path));
17787 next if(skip_lib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017788 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017789 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017790 }
17791 if($OSgroup eq "macos")
17792 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017793 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017794 {
17795 next if(ignore_path($Path));
17796 next if(skip_lib($Path, $LibVersion));
17797 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017798 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
17799 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017800 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017801 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017802 }
17803 }
17804 }
17805 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017806 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017807 }
17808 else {
17809 return ();
17810 }
17811}
17812
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017813sub isCyclical($$)
17814{
17815 my ($Stack, $Value) = @_;
17816 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017817}
17818
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017819sub detectWordSize()
17820{
17821 return "" if(not $GCC_PATH);
17822 if($Cache{"detectWordSize"}) {
17823 return $Cache{"detectWordSize"};
17824 }
17825 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017826 my $Defines = `$GCC_PATH -E -dD \"$TMP_DIR/empty.h\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017827 unlink("$TMP_DIR/empty.h");
17828 my $WSize = 0;
17829 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017830 { # GCC 4
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017831 $WSize = $1;
17832 }
17833 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017834 { # GCC 3
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017835 my $PTRDIFF = $1;
17836 if($PTRDIFF=~/long/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017837 $WSize = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017838 }
17839 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017840 $WSize = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017841 }
17842 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040017843 if(not $WSize) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017844 exitStatus("Error", "can't check WORD size");
17845 }
17846 return ($Cache{"detectWordSize"} = $WSize);
17847}
17848
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040017849sub getWordSize($) {
17850 return $WORD_SIZE{$_[0]};
17851}
17852
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017853sub majorVersion($)
17854{
17855 my $V = $_[0];
17856 return 0 if(not $V);
17857 my @VParts = split(/\./, $V);
17858 return $VParts[0];
17859}
17860
17861sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017862{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017863 my ($V1, $V2) = @_;
17864 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017865 my @V1Parts = split(/\./, $V1);
17866 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017867 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
17868 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017869 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
17870 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
17871 }
17872 return -1 if($#V1Parts < $#V2Parts);
17873 return 1 if($#V1Parts > $#V2Parts);
17874 return 0;
17875}
17876
17877sub read_ABI_Dump($$)
17878{
17879 my ($LibVersion, $Path) = @_;
17880 return if(not $LibVersion or not -e $Path);
17881 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017882 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017883 { # input *.abi
17884 $FilePath = $Path;
17885 }
17886 else
17887 { # input *.abi.tar.gz
17888 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017889 if(not isDump_U($FilePath)) {
17890 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
17891 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017892 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017893
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040017894 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017895
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040017896 my $Line = readLineNum($FilePath, 0);
17897 if($Line=~/xml/)
17898 { # XML format
17899 loadModule("XmlDump");
17900 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017901 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040017902 else
17903 { # Perl Data::Dumper format (default)
17904 open(DUMP, $FilePath);
17905 local $/ = undef;
17906 my $Content = <DUMP>;
17907 close(DUMP);
17908
17909 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
17910 { # remove temp file
17911 unlink($FilePath);
17912 }
17913 if($Content!~/};\s*\Z/) {
17914 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
17915 }
17916 $ABI = eval($Content);
17917 if(not $ABI) {
17918 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
17919 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017920 }
17921 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017922 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040017923 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017924 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017925 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017926 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017927 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017928 $UsedDump{$LibVersion}{"V"} = $DVersion;
17929 if(majorVersion($DVersion) ne majorVersion($ABI_DUMP_VERSION))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017930 { # should be compatible with dumps of the same major version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017931 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017932 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017933 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017934 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017935 elsif(cmpVersions($DVersion, $TOOL_VERSION)>0 and not $ABI->{"ABI_DUMP_VERSION"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017936 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017937 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017938 }
17939 if($UseOldDumps)
17940 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017941 if(cmpVersions($DVersion, $OLDEST_SUPPORTED_VERSION)<0) {
17942 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (older than $OLDEST_SUPPORTED_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017943 }
17944 }
17945 else
17946 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017947 my $Msg = "incompatible version \'$DVersion\' of specified ABI dump (allowed only ".majorVersion($ABI_DUMP_VERSION).".0<=V<=$ABI_DUMP_VERSION)";
17948 if(cmpVersions($DVersion, $OLDEST_SUPPORTED_VERSION)>=0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017949 $Msg .= "\nUse -old-dumps option to use old-version dumps ($OLDEST_SUPPORTED_VERSION<=V<".majorVersion($ABI_DUMP_VERSION).".0)";
17950 }
17951 exitStatus("Dump_Version", $Msg);
17952 }
17953 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017954 if(not checkDump($LibVersion, "2.11"))
17955 { # old ABI dumps
17956 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017957 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040017958 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017959 { # ABI dump created with --binary option
17960 $UsedDump{$LibVersion}{"BinOnly"} = 1;
17961 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017962 else
17963 { # default
17964 $UsedDump{$LibVersion}{"SrcBin"} = 1;
17965 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040017966 if(defined $ABI->{"Mode"}
17967 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017968 { # --ext option
17969 $ExtendedCheck = 1;
17970 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017971 if($ABI->{"Extra"}) {
17972 $ExtraDump = 1;
17973 }
17974
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040017975 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017976 {
17977 $UsedDump{$LibVersion}{"L"} = $Lang;
17978 setLanguage($LibVersion, $Lang);
17979 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017980 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040017981 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017982 }
17983 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017984 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040017985 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017986 if(not $TInfo)
17987 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040017988 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017989 }
17990 my %Tid_TDid = ();
17991 foreach my $TDid (keys(%{$TInfo}))
17992 {
17993 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
17994 {
17995 $MAX_ID = $Tid if($Tid>$MAX_ID);
17996 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
17997 $Tid_TDid{$Tid}{$TDid}=1;
17998 }
17999 }
18000 my %NewID = ();
18001 foreach my $Tid (keys(%Tid_TDid))
18002 {
18003 my @TDids = keys(%{$Tid_TDid{$Tid}});
18004 if($#TDids>=1)
18005 {
18006 foreach my $TDid (@TDids)
18007 {
18008 if($TDid) {
18009 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
18010 }
18011 else
18012 {
18013 if(my $ID = ++$MAX_ID)
18014 {
18015 $NewID{$TDid}{$Tid} = $ID;
18016 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
18017 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
18018 }
18019 }
18020 }
18021 }
18022 else
18023 {
18024 my $TDid = $TDids[0];
18025 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
18026 }
18027 }
18028 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
18029 {
18030 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
18031 if(defined $Info{"BaseType"})
18032 {
18033 my $Bid = $Info{"BaseType"}{"Tid"};
18034 my $BDid = $Info{"BaseType"}{"TDid"};
18035 $BDid="" if(not defined $BDid);
18036 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
18037 $TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"Tid"} = $ID;
18038 }
18039 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
18040 }
18041 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
18042 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018043 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018044 read_Machine_DumpInfo($ABI, $LibVersion);
18045 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018046 if(not $SymbolInfo{$LibVersion})
18047 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018048 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018049 }
18050 if(not keys(%{$SymbolInfo{$LibVersion}}))
18051 { # validation of old-version dumps
18052 if(not $ExtendedCheck) {
18053 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
18054 }
18055 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018056 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018057 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018058 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018059 else
18060 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018061 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018062 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018063 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018064 }
18065 if(not $DepSymbols)
18066 { # Cannot reconstruct DepSymbols. This may result in false
18067 # positives if the old dump is for library 2. Not a problem if
18068 # old dumps are only from old libraries.
18069 $DepSymbols = {};
18070 }
18071 foreach my $Symbol (keys(%{$DepSymbols})) {
18072 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
18073 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018074 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018075 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
18076 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
18077 $SkipTypes{$LibVersion} = $ABI->{"SkipTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018078 if(not $SkipTypes{$LibVersion})
18079 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018080 $SkipTypes{$LibVersion} = $ABI->{"OpaqueTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018081 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018082 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018083 if(not $SkipSymbols{$LibVersion})
18084 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018085 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018086 }
18087 if(not $SkipSymbols{$LibVersion})
18088 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018089 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018090 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018091 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
18092 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
18093 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018094 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018095 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018096 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018097 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018098 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018099 read_Headers_DumpInfo($ABI, $LibVersion);
18100 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040018101 if(not checkDump($LibVersion, "2.10.1")
18102 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018103 { # support for old ABI dumps: added target headers
18104 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
18105 $TargetHeaders{$LibVersion}{get_filename($_)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018106 }
18107 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018108 $Constants{$LibVersion} = $ABI->{"Constants"};
18109 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018110 if(not $NestedNameSpaces{$LibVersion})
18111 { # support for old dumps
18112 # Cannot reconstruct NameSpaces. This may affect design
18113 # of the compatibility report.
18114 $NestedNameSpaces{$LibVersion} = {};
18115 }
18116 # target system type
18117 # needed to adopt HTML report
18118 if(not $DumpSystem)
18119 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018120 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018121 }
18122 # recreate environment
18123 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
18124 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018125 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018126 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018127 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18128 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018129 { # data marked as -size in the dump
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018130 $GlobalDataObject{$LibVersion}{$Symbol}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018131 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018132 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18133 {
18134 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
18135 setLanguage($LibVersion, "C++");
18136 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018137 }
18138 }
18139 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018140 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
18141 {
18142 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
18143 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18144 }
18145 }
18146
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018147 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018148 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018149 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040018150 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018151 {
18152 if(not $Symbol_Library{$LibVersion}{$MnglName}
18153 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
18154 push(@VFunc, $MnglName);
18155 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018156 }
18157 }
18158 translateSymbols(@VFunc, $LibVersion);
18159 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018160 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
18161
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018162 if(not checkDump($LibVersion, "2.20"))
18163 { # support for old ABI dumps
18164 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
18165 {
18166 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
18167
18168 if($TType=~/Struct|Union|Enum|Typedef/)
18169 { # repair complex types first
18170 next;
18171 }
18172
18173 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"})
18174 {
18175 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
18176 if($BType=~/Struct|Union|Enum/i)
18177 {
18178 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
18179 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
18180 }
18181 }
18182 }
18183 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
18184 {
18185 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
18186 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
18187 if($TType=~/Struct|Union|Enum/) {
18188 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
18189 }
18190 }
18191 }
18192
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018193 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040018194 { # order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018195 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
18196 { # support for old ABI dumps < 2.0 (ACC 1.22)
18197 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
18198 {
18199 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
18200 {
18201 if($Access ne "public") {
18202 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
18203 }
18204 }
18205 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
18206 }
18207 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
18208 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018209 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
18210 { # support for old ABI dumps
18211 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
18212 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018213 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
18214 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
18215 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018216 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
18217 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018218 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018219 foreach (keys(%{$TInfo{"Base"}})) {
18220 $Class_SubClasses{$LibVersion}{$_}{$TypeId}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018221 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018222 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018223 if($TInfo{"Type"} eq "MethodPtr")
18224 {
18225 if(defined $TInfo{"Param"})
18226 { # support for old ABI dumps <= 1.17
18227 if(not defined $TInfo{"Param"}{"0"})
18228 {
18229 my $Max = keys(%{$TInfo{"Param"}});
18230 foreach my $Pos (1 .. $Max) {
18231 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
18232 }
18233 delete($TInfo{"Param"}{$Max});
18234 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
18235 }
18236 }
18237 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018238 if($TInfo{"Type"} eq "Typedef" and defined $TInfo{"BaseType"})
18239 {
18240 if(my $BTid = $TInfo{"BaseType"}{"Tid"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018241 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018242 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
18243 if(not $BName)
18244 { # broken type
18245 next;
18246 }
18247 if($TInfo{"Name"} eq $BName)
18248 { # typedef to "class Class"
18249 # should not be registered in TName_Tid
18250 next;
18251 }
18252 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
18253 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018254 }
18255 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018256 }
18257 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
18258 { # classes: class (id1), typedef (artificial, id2 > id1)
18259 $TName_Tid{$LibVersion}{$TInfo{"Name"}} = $TypeId;
18260 }
18261 }
18262
18263 if(not checkDump($LibVersion, "2.15"))
18264 { # support for old ABI dumps
18265 my %Dups = ();
18266 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
18267 {
18268 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018269 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018270 if(not defined $TypeInfo{$LibVersion}{$ClassId})
18271 { # remove template decls
18272 delete($SymbolInfo{$LibVersion}{$InfoId});
18273 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018274 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018275 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040018276 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
18277 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018278 { # templates
18279 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018280 }
18281 }
18282 }
18283
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040018284 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
18285 {
18286 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
18287 { # ABI dumps have no mangled names for C-functions
18288 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
18289 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018290 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
18291 { # support for old ABI dumps
18292 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
18293 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040018294 }
18295
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018296 $Descriptor{$LibVersion}{"Dump"} = 1;
18297}
18298
18299sub read_Machine_DumpInfo($$)
18300{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018301 my ($ABI, $LibVersion) = @_;
18302 if($ABI->{"Arch"}) {
18303 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018304 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018305 if($ABI->{"WordSize"}) {
18306 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018307 }
18308 else
18309 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018310 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018311 }
18312 if(not $WORD_SIZE{$LibVersion})
18313 { # support for old dumps (<1.23)
18314 if(my $Tid = getTypeIdByName("char*", $LibVersion))
18315 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018316 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018317 }
18318 else
18319 {
18320 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018321 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018322 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018323 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
18324 { # any "pointer"-type
18325 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018326 last;
18327 }
18328 }
18329 if($PSize)
18330 { # a pointer type size
18331 $WORD_SIZE{$LibVersion} = $PSize;
18332 }
18333 else {
18334 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
18335 }
18336 }
18337 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018338 if($ABI->{"GccVersion"}) {
18339 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018340 }
18341}
18342
18343sub read_Libs_DumpInfo($$)
18344{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018345 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018346 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
18347 if(not $Library_Symbol{$LibVersion})
18348 { # support for old dumps
18349 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
18350 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018351 if(keys(%{$Library_Symbol{$LibVersion}})
18352 and not $DumpAPI) {
18353 $Descriptor{$LibVersion}{"Libs"} = "OK";
18354 }
18355}
18356
18357sub read_Headers_DumpInfo($$)
18358{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018359 my ($ABI, $LibVersion) = @_;
18360 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018361 and not $DumpAPI) {
18362 $Descriptor{$LibVersion}{"Headers"} = "OK";
18363 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018364 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018365 { # headers info is stored in the old dumps in the different way
18366 if($UseOldDumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018367 and my $Name = $ABI->{"Headers"}{$Identity}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018368 { # support for old dumps: headers info corrected in 1.22
18369 $Identity = $Name;
18370 }
18371 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018372 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018373 }
18374}
18375
18376sub find_libs($$$)
18377{
18378 my ($Path, $Type, $MaxDepth) = @_;
18379 # FIXME: correct the search pattern
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018380 return cmd_find($Path, $Type, ".*\\.".$LIB_EXT."[0-9.]*", $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018381}
18382
18383sub createDescriptor($$)
18384{
18385 my ($LibVersion, $Path) = @_;
18386 if(not $LibVersion or not $Path
18387 or not -e $Path) {
18388 return "";
18389 }
18390 if(-d $Path)
18391 { # directory with headers files and shared objects
18392 return "
18393 <version>
18394 ".$TargetVersion{$LibVersion}."
18395 </version>
18396
18397 <headers>
18398 $Path
18399 </headers>
18400
18401 <libs>
18402 $Path
18403 </libs>";
18404 }
18405 else
18406 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018407 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018408 { # standard XML-descriptor
18409 return readFile($Path);
18410 }
18411 elsif(is_header($Path, 2, $LibVersion))
18412 { # header file
18413 return "
18414 <version>
18415 ".$TargetVersion{$LibVersion}."
18416 </version>
18417
18418 <headers>
18419 $Path
18420 </headers>
18421
18422 <libs>
18423 none
18424 </libs>";
18425 }
18426 elsif(parse_libname($Path, "name", $OStarget))
18427 { # shared object
18428 return "
18429 <version>
18430 ".$TargetVersion{$LibVersion}."
18431 </version>
18432
18433 <headers>
18434 none
18435 </headers>
18436
18437 <libs>
18438 $Path
18439 </libs>";
18440 }
18441 else
18442 { # standard XML-descriptor
18443 return readFile($Path);
18444 }
18445 }
18446}
18447
18448sub detect_lib_default_paths()
18449{
18450 my %LPaths = ();
18451 if($OSgroup eq "bsd")
18452 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018453 if(my $LdConfig = get_CmdPath("ldconfig"))
18454 {
18455 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
18456 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018457 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
18458 {
18459 my $Name = "lib".$1;
18460 if(not defined $LPaths{$Name}) {
18461 $LPaths{$Name} = $2;
18462 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018463 }
18464 }
18465 }
18466 else {
18467 printMsg("WARNING", "can't find ldconfig");
18468 }
18469 }
18470 else
18471 {
18472 if(my $LdConfig = get_CmdPath("ldconfig"))
18473 {
18474 if($SystemRoot and $OSgroup eq "linux")
18475 { # use host (x86) ldconfig with the target (arm) ld.so.conf
18476 if(-e $SystemRoot."/etc/ld.so.conf") {
18477 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
18478 }
18479 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018480 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
18481 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018482 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
18483 {
18484 my ($Name, $Path) = ($1, $2);
18485 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018486 if(not defined $LPaths{$Name})
18487 { # get first element from the list of available paths
18488
18489 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
18490 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
18491 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
18492
18493 $LPaths{$Name} = $Path;
18494 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018495 }
18496 }
18497 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040018498 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018499 printMsg("WARNING", "can't find ldconfig");
18500 }
18501 }
18502 return \%LPaths;
18503}
18504
18505sub detect_bin_default_paths()
18506{
18507 my $EnvPaths = $ENV{"PATH"};
18508 if($OSgroup eq "beos") {
18509 $EnvPaths.=":".$ENV{"BETOOLS"};
18510 }
18511 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018512 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018513 {
18514 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018515 next if(not $Path);
18516 if($SystemRoot
18517 and $Path=~/\A\Q$SystemRoot\E\//)
18518 { # do NOT use binaries from target system
18519 next;
18520 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018521 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018522 }
18523}
18524
18525sub detect_inc_default_paths()
18526{
18527 return () if(not $GCC_PATH);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018528 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018529 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018530 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018531 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018532 next if(index($Line, "/cc1plus ")!=-1);
18533
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018534 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
18535 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018536 my $Path = realpath($1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018537 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018538 if(index($Path, "c++")!=-1
18539 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018540 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018541 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018542 if(not defined $MAIN_CPP_DIR
18543 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
18544 $MAIN_CPP_DIR = $Path;
18545 }
18546 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018547 elsif(index($Path, "gcc")!=-1) {
18548 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018549 }
18550 else
18551 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018552 if($Path=~/local[\/\\]+include/)
18553 { # local paths
18554 next;
18555 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018556 if($SystemRoot
18557 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
18558 { # The GCC include path for user headers is not a part of the system root
18559 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
18560 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
18561 next;
18562 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018563 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018564 }
18565 }
18566 }
18567 unlink("$TMP_DIR/empty.h");
18568 return %DPaths;
18569}
18570
18571sub detect_default_paths($)
18572{
18573 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
18574 my $Search = $_[0];
18575 if($Search!~/inc/) {
18576 $HSearch = 0;
18577 }
18578 if($Search!~/lib/) {
18579 $LSearch = 0;
18580 }
18581 if($Search!~/bin/) {
18582 $BSearch = 0;
18583 }
18584 if($Search!~/gcc/) {
18585 $GSearch = 0;
18586 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018587 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018588 { # <search_headers> section of the XML descriptor
18589 # do NOT search for systems headers
18590 $HSearch = 0;
18591 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018592 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018593 { # <search_headers> section of the XML descriptor
18594 # do NOT search for systems headers
18595 $LSearch = 0;
18596 }
18597 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
18598 { # additional search paths
18599 next if($Type eq "include" and not $HSearch);
18600 next if($Type eq "lib" and not $LSearch);
18601 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018602 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018603 }
18604 if($OSgroup ne "windows")
18605 { # unix-like
18606 foreach my $Type ("include", "lib", "bin")
18607 { # automatic detection of system "devel" directories
18608 next if($Type eq "include" and not $HSearch);
18609 next if($Type eq "lib" and not $LSearch);
18610 next if($Type eq "bin" and not $BSearch);
18611 my ($UsrDir, $RootDir) = ("/usr", "/");
18612 if($SystemRoot and $Type ne "bin")
18613 { # 1. search for target headers and libraries
18614 # 2. use host commands: ldconfig, readelf, etc.
18615 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
18616 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018617 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018618 if(-d $RootDir."/".$Type)
18619 { # if "/lib" is symbolic link
18620 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018621 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018622 }
18623 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018624 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018625 }
18626 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018627 if(-d $UsrDir)
18628 {
18629 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018630 if(-d $UsrDir."/".$Type)
18631 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018632 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018633 }
18634 }
18635 }
18636 }
18637 if($BSearch)
18638 {
18639 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018640 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018641 }
18642 # check environment variables
18643 if($OSgroup eq "beos")
18644 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018645 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018646 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018647 if($_ eq ".") {
18648 next;
18649 }
18650 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
18651 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
18652 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018653 }
18654 }
18655 if($HSearch)
18656 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018657 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
18658 split(/:|;/, $ENV{"BEINCLUDES"})
18659 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018660 }
18661 if($LSearch)
18662 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018663 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
18664 split(/:|;/, $ENV{"BELIBRARIES"}),
18665 split(/:|;/, $ENV{"LIBRARY_PATH"})
18666 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018667 }
18668 }
18669 if($LSearch)
18670 { # using linker to get system paths
18671 if(my $LPaths = detect_lib_default_paths())
18672 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018673 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018674 foreach my $Name (keys(%{$LPaths}))
18675 {
18676 if($SystemRoot
18677 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
18678 { # wrong ldconfig configuration
18679 # check your <sysroot>/etc/ld.so.conf
18680 next;
18681 }
18682 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018683 if(my $Dir = get_dirname($LPaths->{$Name})) {
18684 $Dirs{$Dir} = 1;
18685 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018686 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018687 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018688 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018689 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018690 }
18691 if($BSearch)
18692 {
18693 if($CrossGcc)
18694 { # --cross-gcc=arm-linux-gcc
18695 if(-e $CrossGcc)
18696 { # absolute or relative path
18697 $GCC_PATH = get_abs_path($CrossGcc);
18698 }
18699 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
18700 { # command name
18701 $GCC_PATH = $CrossGcc;
18702 }
18703 else {
18704 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
18705 }
18706 if($GCC_PATH=~/\s/) {
18707 $GCC_PATH = "\"".$GCC_PATH."\"";
18708 }
18709 }
18710 }
18711 if($GSearch)
18712 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018713 if(not $CrossGcc)
18714 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018715 $GCC_PATH = get_CmdPath("gcc");
18716 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018717 if(not $GCC_PATH)
18718 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018719 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018720 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018721 if(my @GCCs = cmd_find($Path, "", ".*/gcc-[0-9.]*", 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018722 { # select the latest version
18723 @GCCs = sort {$b cmp $a} @GCCs;
18724 if(check_gcc($GCCs[0], "3"))
18725 {
18726 $GCC_PATH = $GCCs[0];
18727 last;
18728 }
18729 }
18730 }
18731 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018732 if(not $GCC_PATH) {
18733 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
18734 }
18735 if(not $CheckObjectsOnly_Opt)
18736 {
18737 if(my $GCC_Ver = get_dumpversion($GCC_PATH))
18738 {
18739 my $GccTarget = get_dumpmachine($GCC_PATH);
18740 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget)");
18741 if($GccTarget=~/symbian/)
18742 {
18743 $OStarget = "symbian";
18744 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
18745 }
18746 }
18747 else {
18748 exitStatus("Error", "something is going wrong with the GCC compiler");
18749 }
18750 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018751 if($HSearch)
18752 {
18753 if(not $NoStdInc)
18754 { # do NOT search in GCC standard paths
18755 my %DPaths = detect_inc_default_paths();
18756 @DefaultCppPaths = @{$DPaths{"Cpp"}};
18757 @DefaultGccPaths = @{$DPaths{"Gcc"}};
18758 @DefaultIncPaths = @{$DPaths{"Inc"}};
18759 push_U($SystemPaths{"include"}, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018760 }
18761 }
18762 }
18763 if($HSearch)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018764 { # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018765 my $IncPath = "/usr/include";
18766 if($SystemRoot) {
18767 $IncPath = $SystemRoot.$IncPath;
18768 }
18769 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018770 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018771 }
18772 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018773
18774 if($ExtraInfo)
18775 {
18776 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
18777 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
18778 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018779}
18780
18781sub getLIB_EXT($)
18782{
18783 my $Target = $_[0];
18784 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
18785 return $Ext;
18786 }
18787 return $OS_LibExt{$LIB_TYPE}{"default"};
18788}
18789
18790sub getAR_EXT($)
18791{
18792 my $Target = $_[0];
18793 if(my $Ext = $OS_Archive{$Target}) {
18794 return $Ext;
18795 }
18796 return $OS_Archive{"default"};
18797}
18798
18799sub get_dumpversion($)
18800{
18801 my $Cmd = $_[0];
18802 return "" if(not $Cmd);
18803 if($Cache{"get_dumpversion"}{$Cmd}) {
18804 return $Cache{"get_dumpversion"}{$Cmd};
18805 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018806 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018807 chomp($V);
18808 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
18809}
18810
18811sub get_dumpmachine($)
18812{
18813 my $Cmd = $_[0];
18814 return "" if(not $Cmd);
18815 if($Cache{"get_dumpmachine"}{$Cmd}) {
18816 return $Cache{"get_dumpmachine"}{$Cmd};
18817 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018818 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018819 chomp($Machine);
18820 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
18821}
18822
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018823sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018824{
18825 my $Cmd = $_[0];
18826 return "" if(not $Cmd);
18827 my @Options = (
18828 "--version",
18829 "-help"
18830 );
18831 foreach my $Opt (@Options)
18832 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018833 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018834 if($Info) {
18835 return 1;
18836 }
18837 }
18838 return 0;
18839}
18840
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018841sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018842{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018843 my ($Cmd, $ReqVer) = @_;
18844 return 0 if(not $Cmd or not $ReqVer);
18845 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
18846 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018847 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018848 if(my $GccVer = get_dumpversion($Cmd))
18849 {
18850 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
18851 if(cmpVersions($GccVer, $ReqVer)>=0) {
18852 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
18853 }
18854 }
18855 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018856}
18857
18858sub get_depth($)
18859{
18860 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018861 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018862 }
18863 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
18864}
18865
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018866sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018867{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018868 return if($Cache{"registerGccHeaders"}); # this function should be called once
18869
18870 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018871 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018872 my @Headers = cmd_find($Path,"f");
18873 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
18874 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018875 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018876 my $FileName = get_filename($HPath);
18877 if(not defined $DefaultGccHeader{$FileName})
18878 { # skip duplicated
18879 $DefaultGccHeader{$FileName} = $HPath;
18880 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018881 }
18882 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018883 $Cache{"registerGccHeaders"} = 1;
18884}
18885
18886sub registerCppHeaders()
18887{
18888 return if($Cache{"registerCppHeaders"}); # this function should be called once
18889
18890 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018891 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018892 my @Headers = cmd_find($CppDir,"f");
18893 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
18894 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018895 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018896 my $FileName = get_filename($Path);
18897 if(not defined $DefaultCppHeader{$FileName})
18898 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018899 $DefaultCppHeader{$FileName} = $Path;
18900 }
18901 }
18902 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018903 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018904}
18905
18906sub parse_libname($$$)
18907{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018908 return "" if(not $_[0]);
18909 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
18910 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018911 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018912 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
18913}
18914
18915sub parse_libname_I($$$)
18916{
18917 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018918 if($Target eq "symbian") {
18919 return parse_libname_symbian($Name, $Type);
18920 }
18921 elsif($Target eq "windows") {
18922 return parse_libname_windows($Name, $Type);
18923 }
18924 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018925 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018926 { # libSDL-1.2.so.0.7.1
18927 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018928 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018929 if($Type eq "name")
18930 { # libSDL-1.2
18931 # libwbxml2
18932 return $2;
18933 }
18934 elsif($Type eq "name+ext")
18935 { # libSDL-1.2.so
18936 # libwbxml2.so
18937 return $1;
18938 }
18939 elsif($Type eq "version")
18940 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018941 if(defined $7
18942 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018943 { # 0.7.1
18944 return $7;
18945 }
18946 else
18947 { # libc-2.5.so (=>2.5 version)
18948 my $MV = $5;
18949 $MV=~s/\A[\-\_]+//g;
18950 return $MV;
18951 }
18952 }
18953 elsif($Type eq "short")
18954 { # libSDL
18955 # libwbxml2
18956 return $3;
18957 }
18958 elsif($Type eq "shortest")
18959 { # SDL
18960 # wbxml
18961 return shortest_name($3);
18962 }
18963 }
18964 return "";# error
18965}
18966
18967sub parse_libname_symbian($$)
18968{
18969 my ($Name, $Type) = @_;
18970 my $Ext = getLIB_EXT("symbian");
18971 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
18972 { # libpthread{00010001}.dso
18973 if($Type eq "name")
18974 { # libpthread{00010001}
18975 return $2;
18976 }
18977 elsif($Type eq "name+ext")
18978 { # libpthread{00010001}.dso
18979 return $1;
18980 }
18981 elsif($Type eq "version")
18982 { # 00010001
18983 my $V = $4;
18984 $V=~s/\{(.+)\}/$1/;
18985 return $V;
18986 }
18987 elsif($Type eq "short")
18988 { # libpthread
18989 return $3;
18990 }
18991 elsif($Type eq "shortest")
18992 { # pthread
18993 return shortest_name($3);
18994 }
18995 }
18996 return "";# error
18997}
18998
18999sub parse_libname_windows($$)
19000{
19001 my ($Name, $Type) = @_;
19002 my $Ext = getLIB_EXT("windows");
19003 if($Name=~/((.+?)\.$Ext)\Z/)
19004 { # netapi32.dll
19005 if($Type eq "name")
19006 { # netapi32
19007 return $2;
19008 }
19009 elsif($Type eq "name+ext")
19010 { # netapi32.dll
19011 return $1;
19012 }
19013 elsif($Type eq "version")
19014 { # DLL version embedded
19015 # at binary-level
19016 return "";
19017 }
19018 elsif($Type eq "short")
19019 { # netapi32
19020 return $2;
19021 }
19022 elsif($Type eq "shortest")
19023 { # netapi
19024 return shortest_name($2);
19025 }
19026 }
19027 return "";# error
19028}
19029
19030sub shortest_name($)
19031{
19032 my $Name = $_[0];
19033 # remove prefix
19034 $Name=~s/\A(lib|open)//;
19035 # remove suffix
19036 $Name=~s/[\W\d_]+\Z//i;
19037 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
19038 return $Name;
19039}
19040
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019041sub createSymbolsList($$$$$)
19042{
19043 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
19044 read_ABI_Dump(1, $DPath);
19045 if(not $CheckObjectsOnly) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019046 prepareSymbols(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019047 }
19048 my %SymbolHeaderLib = ();
19049 my $Total = 0;
19050 # Get List
19051 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
19052 {
19053 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019054 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019055 next;
19056 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019057 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019058 { # skip other symbols
19059 next;
19060 }
19061 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
19062 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019063 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019064 next;
19065 }
19066 my $DyLib = $Symbol_Library{1}{$Symbol};
19067 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019068 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019069 next;
19070 }
19071 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
19072 $Total+=1;
19073 }
19074 # Draw List
19075 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
19076 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
19077 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
19078 {
19079 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
19080 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019081 my %NS_Symbol = ();
19082 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019083 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019084 }
19085 foreach my $NameSpace (sort keys(%NS_Symbol))
19086 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019087 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019088 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
19089 foreach my $Symbol (@SortedInterfaces)
19090 {
19091 my $SubReport = "";
19092 my $Signature = get_Signature($Symbol, 1);
19093 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019094 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019095 }
19096 if($Symbol=~/\A(_Z|\?)/)
19097 {
19098 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019099 $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 +040019100 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019101 else {
19102 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
19103 }
19104 }
19105 else
19106 {
19107 if($Signature) {
19108 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
19109 }
19110 else {
19111 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
19112 }
19113 }
19114 $SYMBOLS_LIST .= $SubReport;
19115 }
19116 }
19117 $SYMBOLS_LIST .= "<br/>\n";
19118 }
19119 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019120 # clear info
19121 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
19122 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
19123 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
19124 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019125 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019126 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019127 my $CssStyles = readModule("Styles", "SymbolsList.css");
19128 my $JScripts = readModule("Scripts", "Sections.js");
19129 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019130 my $Title = "$LName: public symbols";
19131 my $Keywords = "$LName, API, symbols";
19132 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019133 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019134 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019135 <br/><br/><hr/>\n".getReportFooter($LName, 1)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019136 <div style='height:999px;'></div></body></html>";
19137 writeFile($SaveTo, $SYMBOLS_LIST);
19138}
19139
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019140sub add_target_libs($)
19141{
19142 foreach (@{$_[0]}) {
19143 $TargetLibs{$_} = 1;
19144 }
19145}
19146
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019147sub is_target_lib($)
19148{
19149 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019150 if(not $LName) {
19151 return 0;
19152 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019153 if($TargetLibraryName
19154 and $LName!~/\Q$TargetLibraryName\E/) {
19155 return 0;
19156 }
19157 if(keys(%TargetLibs)
19158 and not $TargetLibs{$LName}
19159 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
19160 return 0;
19161 }
19162 return 1;
19163}
19164
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019165sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019166{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019167 my ($H, $V) = @_;
19168 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019169 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019170 if($TargetHeaders{$V}{$H}) {
19171 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019172 }
19173 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019174 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019175}
19176
19177sub checkVersionNum($$)
19178{
19179 my ($LibVersion, $Path) = @_;
19180 if(my $VerNum = $TargetVersion{$LibVersion}) {
19181 return $VerNum;
19182 }
19183 my $UsedAltDescr = 0;
19184 foreach my $Part (split(/\s*,\s*/, $Path))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019185 { # try to get version string from file path
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019186 next if(isDump($Part)); # ABI dump
19187 next if($Part=~/\.(xml|desc)\Z/i); # XML descriptor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019188 my $VerNum = "";
19189 if(parse_libname($Part, "name", $OStarget))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019190 {
19191 $UsedAltDescr = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019192 $VerNum = parse_libname($Part, "version", $OStarget);
19193 if(not $VerNum) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019194 $VerNum = readStrVer($Part);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019195 }
19196 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019197 elsif(is_header($Part, 2, $LibVersion) or -d $Part)
19198 {
19199 $UsedAltDescr = 1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019200 $VerNum = readStrVer($Part);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019201 }
19202 if($VerNum ne "")
19203 {
19204 $TargetVersion{$LibVersion} = $VerNum;
19205 if($DumpAPI) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019206 printMsg("WARNING", "setting version number to $VerNum (use -vnum option to change it)");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019207 }
19208 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019209 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 +040019210 }
19211 return $TargetVersion{$LibVersion};
19212 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019213 }
19214 if($UsedAltDescr)
19215 {
19216 if($DumpAPI) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019217 exitStatus("Error", "version number is not set (use -vnum option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019218 }
19219 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019220 exitStatus("Error", ($LibVersion==1?"1st":"2nd")." version number is not set (use -v$LibVersion option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019221 }
19222 }
19223}
19224
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019225sub readStrVer($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019226{
19227 my $Str = $_[0];
19228 return "" if(not $Str);
19229 $Str=~s/\Q$TargetLibraryName\E//g;
19230 if($Str=~/(\/|\\|\w|\A)[\-\_]*(\d+[\d\.\-]+\d+|\d+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019231 { # .../libssh-0.4.0/...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019232 return $2;
19233 }
19234 elsif(my $V = parse_libname($Str, "version", $OStarget)) {
19235 return $V;
19236 }
19237 return "";
19238}
19239
19240sub readLibs($)
19241{
19242 my $LibVersion = $_[0];
19243 if($OStarget eq "windows")
19244 { # dumpbin.exe will crash
19245 # without VS Environment
19246 check_win32_env();
19247 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019248 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019249 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019250 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019251}
19252
19253sub dump_sorting($)
19254{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040019255 my $Hash = $_[0];
19256 return [] if(not $Hash);
19257 my @Keys = keys(%{$Hash});
19258 return [] if($#Keys<0);
19259 if($Keys[0]=~/\A\d+\Z/)
19260 { # numbers
19261 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019262 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040019263 else
19264 { # strings
19265 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019266 }
19267}
19268
19269sub printMsg($$)
19270{
19271 my ($Type, $Msg) = @_;
19272 if($Type!~/\AINFO/) {
19273 $Msg = $Type.": ".$Msg;
19274 }
19275 if($Type!~/_C\Z/) {
19276 $Msg .= "\n";
19277 }
19278 if($Quiet)
19279 { # --quiet option
19280 appendFile($COMMON_LOG_PATH, $Msg);
19281 }
19282 else
19283 {
19284 if($Type eq "ERROR") {
19285 print STDERR $Msg;
19286 }
19287 else {
19288 print $Msg;
19289 }
19290 }
19291}
19292
19293sub exitStatus($$)
19294{
19295 my ($Code, $Msg) = @_;
19296 printMsg("ERROR", $Msg);
19297 exit($ERROR_CODE{$Code});
19298}
19299
19300sub exitReport()
19301{ # the tool has run without any errors
19302 printReport();
19303 if($COMPILE_ERRORS)
19304 { # errors in headers may add false positives/negatives
19305 exit($ERROR_CODE{"Compile_Error"});
19306 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019307 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
19308 { # --binary
19309 exit($ERROR_CODE{"Incompatible"});
19310 }
19311 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
19312 { # --source
19313 exit($ERROR_CODE{"Incompatible"});
19314 }
19315 elsif($RESULT{"Source"}{"Problems"}
19316 or $RESULT{"Binary"}{"Problems"})
19317 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019318 exit($ERROR_CODE{"Incompatible"});
19319 }
19320 else {
19321 exit($ERROR_CODE{"Compatible"});
19322 }
19323}
19324
19325sub readRules($)
19326{
19327 my $Kind = $_[0];
19328 if(not -f $RULES_PATH{$Kind}) {
19329 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
19330 }
19331 my $Content = readFile($RULES_PATH{$Kind});
19332 while(my $Rule = parseTag(\$Content, "rule"))
19333 {
19334 my $RId = parseTag(\$Rule, "id");
19335 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
19336 foreach my $Prop (@Properties) {
19337 if(my $Value = parseTag(\$Rule, lc($Prop)))
19338 {
19339 $Value=~s/\n[ ]*//;
19340 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
19341 }
19342 }
19343 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
19344 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
19345 }
19346 else {
19347 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
19348 }
19349 }
19350}
19351
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019352sub getReportPath($)
19353{
19354 my $Level = $_[0];
19355 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
19356 if($Level eq "Binary")
19357 {
19358 if($BinaryReportPath)
19359 { # --bin-report-path
19360 return $BinaryReportPath;
19361 }
19362 elsif($OutputReportPath)
19363 { # --report-path
19364 return $OutputReportPath;
19365 }
19366 else
19367 { # default
19368 return $Dir."/abi_compat_report.$ReportFormat";
19369 }
19370 }
19371 elsif($Level eq "Source")
19372 {
19373 if($SourceReportPath)
19374 { # --src-report-path
19375 return $SourceReportPath;
19376 }
19377 elsif($OutputReportPath)
19378 { # --report-path
19379 return $OutputReportPath;
19380 }
19381 else
19382 { # default
19383 return $Dir."/src_compat_report.$ReportFormat";
19384 }
19385 }
19386 else
19387 {
19388 if($OutputReportPath)
19389 { # --report-path
19390 return $OutputReportPath;
19391 }
19392 else
19393 { # default
19394 return $Dir."/compat_report.$ReportFormat";
19395 }
19396 }
19397}
19398
19399sub printStatMsg($)
19400{
19401 my $Level = $_[0];
19402 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
19403}
19404
19405sub listAffected($)
19406{
19407 my $Level = $_[0];
19408 my $List = "";
19409 foreach (keys(%{$TotalAffected{$Level}}))
19410 {
19411 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
19412 { # skip "Low"-severity problems
19413 next;
19414 }
19415 $List .= "$_\n";
19416 }
19417 my $Dir = get_dirname(getReportPath($Level));
19418 if($Level eq "Binary") {
19419 writeFile($Dir."/abi_affected.txt", $List);
19420 }
19421 elsif($Level eq "Source") {
19422 writeFile($Dir."/src_affected.txt", $List);
19423 }
19424}
19425
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019426sub printReport()
19427{
19428 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019429 createReport();
19430 if($JoinReport or $DoubleReport)
19431 {
19432 if($RESULT{"Binary"}{"Problems"}
19433 or $RESULT{"Source"}{"Problems"}) {
19434 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019435 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019436 else {
19437 printMsg("INFO", "result: COMPATIBLE");
19438 }
19439 printStatMsg("Binary");
19440 printStatMsg("Source");
19441 if($ListAffected)
19442 { # --list-affected
19443 listAffected("Binary");
19444 listAffected("Source");
19445 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019446 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019447 elsif($BinaryOnly)
19448 {
19449 if($RESULT{"Binary"}{"Problems"}) {
19450 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
19451 }
19452 else {
19453 printMsg("INFO", "result: COMPATIBLE");
19454 }
19455 printStatMsg("Binary");
19456 if($ListAffected)
19457 { # --list-affected
19458 listAffected("Binary");
19459 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019460 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019461 elsif($SourceOnly)
19462 {
19463 if($RESULT{"Source"}{"Problems"}) {
19464 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
19465 }
19466 else {
19467 printMsg("INFO", "result: COMPATIBLE");
19468 }
19469 printStatMsg("Source");
19470 if($ListAffected)
19471 { # --list-affected
19472 listAffected("Source");
19473 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019474 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019475 if($StdOut)
19476 {
19477 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040019478 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019479 printMsg("INFO", "compatibility report has been generated to stdout");
19480 }
19481 else
19482 { # default
19483 printMsg("INFO", "compatibility reports have been generated to stdout");
19484 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019485 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019486 else
19487 {
19488 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040019489 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019490 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
19491 }
19492 elsif($DoubleReport)
19493 { # default
19494 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
19495 }
19496 elsif($BinaryOnly)
19497 { # --binary
19498 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
19499 }
19500 elsif($SourceOnly)
19501 { # --source
19502 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
19503 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019504 }
19505}
19506
19507sub check_win32_env()
19508{
19509 if(not $ENV{"DevEnvDir"}
19510 or not $ENV{"LIB"}) {
19511 exitStatus("Error", "can't start without VS environment (vsvars32.bat)");
19512 }
19513}
19514
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019515sub diffSets($$)
19516{
19517 my ($S1, $S2) = @_;
19518 my @SK1 = keys(%{$S1});
19519 my @SK2 = keys(%{$S2});
19520 if($#SK1!=$#SK2) {
19521 return 1;
19522 }
19523 foreach my $K1 (@SK1)
19524 {
19525 if(not defined $S2->{$K1}) {
19526 return 1;
19527 }
19528 }
19529 return 0;
19530}
19531
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019532sub create_ABI_Dump()
19533{
19534 if(not -e $DumpAPI) {
19535 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
19536 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019537 my @DParts = split(/\s*,\s*/, $DumpAPI);
19538 foreach my $Part (@DParts)
19539 {
19540 if(not -e $Part) {
19541 exitStatus("Access_Error", "can't access \'$Part\'");
19542 }
19543 }
19544 checkVersionNum(1, $DumpAPI);
19545 foreach my $Part (@DParts)
19546 {
19547 if(isDump($Part)) {
19548 read_ABI_Dump(1, $Part);
19549 }
19550 else {
19551 readDescriptor(1, createDescriptor(1, $Part));
19552 }
19553 }
19554 initLogging(1);
19555 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019556
19557 # check the archive utilities
19558 if($OSgroup eq "windows")
19559 { # using zip
19560 my $ZipCmd = get_CmdPath("zip");
19561 if(not $ZipCmd) {
19562 exitStatus("Not_Found", "can't find \"zip\"");
19563 }
19564 }
19565 else
19566 { # using tar and gzip
19567 my $TarCmd = get_CmdPath("tar");
19568 if(not $TarCmd) {
19569 exitStatus("Not_Found", "can't find \"tar\"");
19570 }
19571 my $GzipCmd = get_CmdPath("gzip");
19572 if(not $GzipCmd) {
19573 exitStatus("Not_Found", "can't find \"gzip\"");
19574 }
19575 }
19576
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019577 if(not $Descriptor{1}{"Dump"})
19578 {
19579 if(not $CheckHeadersOnly) {
19580 readLibs(1);
19581 }
19582 if($CheckHeadersOnly) {
19583 setLanguage(1, "C++");
19584 }
19585 if(not $CheckObjectsOnly) {
19586 searchForHeaders(1);
19587 }
19588 $WORD_SIZE{1} = detectWordSize();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019589 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019590 if(not $Descriptor{1}{"Dump"})
19591 {
19592 if($Descriptor{1}{"Headers"}) {
19593 readHeaders(1);
19594 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019595 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019596 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019597 if(not keys(%{$SymbolInfo{1}}))
19598 { # check if created dump is valid
19599 if(not $ExtendedCheck and not $CheckObjectsOnly)
19600 {
19601 if($CheckHeadersOnly) {
19602 exitStatus("Empty_Set", "the set of public symbols is empty");
19603 }
19604 else {
19605 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
19606 }
19607 }
19608 }
19609 my %HeadersInfo = ();
19610 foreach my $HPath (keys(%{$Registered_Headers{1}}))
19611 { # headers info stored without paths in the dump
19612 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
19613 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019614 if($ExtraDump)
19615 { # add unmangled names to the ABI dump
19616 my @Names = ();
19617 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
19618 {
19619 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
19620 push(@Names, $MnglName);
19621 }
19622 }
19623 translateSymbols(@Names, 1);
19624 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
19625 {
19626 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
19627 {
19628 if(my $Unmangled = $tr_name{$MnglName})
19629 {
19630 if($MnglName ne $Unmangled) {
19631 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
19632 }
19633 }
19634 }
19635 }
19636 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019637 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019638 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019639 "TypeInfo" => $TypeInfo{1},
19640 "SymbolInfo" => $SymbolInfo{1},
19641 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019642 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019643 "SymbolVersion" => $SymVer{1},
19644 "LibraryVersion" => $Descriptor{1}{"Version"},
19645 "LibraryName" => $TargetLibraryName,
19646 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019647 "SkipTypes" => $SkipTypes{1},
19648 "SkipSymbols" => $SkipSymbols{1},
19649 "SkipNameSpaces" => $SkipNameSpaces{1},
19650 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019651 "Headers" => \%HeadersInfo,
19652 "Constants" => $Constants{1},
19653 "NameSpaces" => $NestedNameSpaces{1},
19654 "Target" => $OStarget,
19655 "Arch" => getArch(1),
19656 "WordSize" => $WORD_SIZE{1},
19657 "GccVersion" => get_dumpversion($GCC_PATH),
19658 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
19659 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
19660 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019661 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019662 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019663 }
19664 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019665 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019666 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019667 if($ExtendedCheck)
19668 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019669 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019670 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019671 if($BinaryOnly)
19672 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019673 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019674 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019675 if($ExtraDump)
19676 { # --extra-info
19677 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
19678 $ABI{"Extra"} = 1;
19679 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019680
19681 my $ABI_DUMP = "";
19682 if($UseXML)
19683 {
19684 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019685 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019686 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019687 else
19688 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019689 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019690 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019691 if($StdOut)
19692 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019693 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019694 printMsg("INFO", "ABI dump has been generated to stdout");
19695 return;
19696 }
19697 else
19698 { # write to gzipped file
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019699 my $DumpPath = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{1}{"Version"}.".abi";
19700 $DumpPath .= ".".$AR_EXT; # gzipped by default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019701 if($OutputDumpPath)
19702 { # user defined path
19703 $DumpPath = $OutputDumpPath;
19704 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019705 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019706 my ($DDir, $DName) = separate_path($DumpPath);
19707 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019708 if(not $Archive) {
19709 $DPath = $DumpPath;
19710 }
19711
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019712 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019713
19714 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019715 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019716 close(DUMP);
19717
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019718 if(not -s $DPath) {
19719 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
19720 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019721 if($Archive) {
19722 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019723 }
19724
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019725 if(not $OutputDumpPath)
19726 {
19727 printMsg("INFO", "library ABI has been dumped to:\n $DumpPath");
19728 printMsg("INFO", "you can transfer this dump everywhere and use instead of the ".$Descriptor{1}{"Version"}." version descriptor");
19729 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019730 }
19731}
19732
19733sub quickEmptyReports()
19734{ # Quick "empty" reports
19735 # 4 times faster than merging equal dumps
19736 # NOTE: the dump contains the "LibraryVersion" attribute
19737 # if you change the version, then your dump will be different
19738 # OVERCOME: use -v1 and v2 options for comparing dumps
19739 # and don't change version in the XML descriptor (and dumps)
19740 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
19741 if(-s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
19742 {
19743 my $FilePath1 = unpackDump($Descriptor{1}{"Path"});
19744 my $FilePath2 = unpackDump($Descriptor{2}{"Path"});
19745 if($FilePath1 and $FilePath2)
19746 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019747 my $Line = readLineNum($FilePath1, 0);
19748 if($Line=~/xml/)
19749 { # XML format
19750 # is not supported yet
19751 return;
19752 }
19753
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019754 local $/ = undef;
19755
19756 open(DUMP1, $FilePath1);
19757 my $Content1 = <DUMP1>;
19758 close(DUMP1);
19759
19760 open(DUMP2, $FilePath2);
19761 my $Content2 = <DUMP2>;
19762 close(DUMP2);
19763
19764 if($Content1 eq $Content2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019765 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019766 # clean memory
19767 undef $Content2;
19768
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019769 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019770 my $ABIdump = eval($Content1);
19771
19772 # clean memory
19773 undef $Content1;
19774
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019775 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019776 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 +040019777 }
19778 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019779 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019780 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
19781 }
19782 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019783 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019784 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
19785 }
19786 read_Headers_DumpInfo($ABIdump, 1);
19787 read_Libs_DumpInfo($ABIdump, 1);
19788 read_Machine_DumpInfo($ABIdump, 1);
19789 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019790
19791 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
19792 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
19793
19794 %{$CheckedSymbols{"Binary"}} = %{$ABIdump->{"SymbolInfo"}};
19795 %{$CheckedSymbols{"Source"}} = %{$ABIdump->{"SymbolInfo"}};
19796
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019797 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
19798 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
19799 exitReport();
19800 }
19801 }
19802 }
19803}
19804
19805sub initLogging($)
19806{
19807 my $LibVersion = $_[0];
19808 # create log directory
19809 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
19810 if($OutputLogPath{$LibVersion})
19811 { # user-defined by -log-path option
19812 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
19813 }
19814 if($LogMode ne "n") {
19815 mkpath($LOG_DIR);
19816 }
19817 $LOG_PATH{$LibVersion} = get_abs_path($LOG_DIR)."/".$LOG_FILE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019818 if($Debug)
19819 { # debug directory
19820 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019821
19822 if(not $ExtraInfo)
19823 { # enable --extra-info
19824 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
19825 }
19826
19827 # enable --extra-dump
19828 $ExtraDump = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019829 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040019830 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019831}
19832
19833sub writeLog($$)
19834{
19835 my ($LibVersion, $Msg) = @_;
19836 if($LogMode ne "n") {
19837 appendFile($LOG_PATH{$LibVersion}, $Msg);
19838 }
19839}
19840
19841sub resetLogging($)
19842{
19843 my $LibVersion = $_[0];
19844 if($LogMode!~/a|n/)
19845 { # remove old log
19846 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040019847 if($Debug) {
19848 rmtree($DEBUG_PATH{$LibVersion});
19849 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019850 }
19851}
19852
19853sub printErrorLog($)
19854{
19855 my $LibVersion = $_[0];
19856 if($LogMode ne "n") {
19857 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
19858 }
19859}
19860
19861sub isDump($)
19862{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019863 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz|\.zip|\.xml|)\Z/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019864 return $1;
19865 }
19866 return 0;
19867}
19868
19869sub isDump_U($)
19870{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019871 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019872 return $1;
19873 }
19874 return 0;
19875}
19876
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019877sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019878{
19879 # read input XML descriptors or ABI dumps
19880 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040019881 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019882 }
19883 my @DParts1 = split(/\s*,\s*/, $Descriptor{1}{"Path"});
19884 foreach my $Part (@DParts1)
19885 {
19886 if(not -e $Part) {
19887 exitStatus("Access_Error", "can't access \'$Part\'");
19888 }
19889 }
19890 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040019891 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019892 }
19893 my @DParts2 = split(/\s*,\s*/, $Descriptor{2}{"Path"});
19894 foreach my $Part (@DParts2)
19895 {
19896 if(not -e $Part) {
19897 exitStatus("Access_Error", "can't access \'$Part\'");
19898 }
19899 }
19900 detect_default_paths("bin"); # to extract dumps
19901 if($#DParts1==0 and $#DParts2==0
19902 and isDump($Descriptor{1}{"Path"})
19903 and isDump($Descriptor{2}{"Path"}))
19904 { # optimization: equal ABI dumps
19905 quickEmptyReports();
19906 }
19907 checkVersionNum(1, $Descriptor{1}{"Path"});
19908 checkVersionNum(2, $Descriptor{2}{"Path"});
19909 printMsg("INFO", "preparation, please wait ...");
19910 foreach my $Part (@DParts1)
19911 {
19912 if(isDump($Part)) {
19913 read_ABI_Dump(1, $Part);
19914 }
19915 else {
19916 readDescriptor(1, createDescriptor(1, $Part));
19917 }
19918 }
19919 foreach my $Part (@DParts2)
19920 {
19921 if(isDump($Part)) {
19922 read_ABI_Dump(2, $Part);
19923 }
19924 else {
19925 readDescriptor(2, createDescriptor(2, $Part));
19926 }
19927 }
19928 initLogging(1);
19929 initLogging(2);
19930 # check consistency
19931 if(not $Descriptor{1}{"Headers"}
19932 and not $Descriptor{1}{"Libs"}) {
19933 exitStatus("Error", "descriptor d1 does not contain both header files and libraries info");
19934 }
19935 if(not $Descriptor{2}{"Headers"}
19936 and not $Descriptor{2}{"Libs"}) {
19937 exitStatus("Error", "descriptor d2 does not contain both header files and libraries info");
19938 }
19939 if($Descriptor{1}{"Headers"} and not $Descriptor{1}{"Libs"}
19940 and not $Descriptor{2}{"Headers"} and $Descriptor{2}{"Libs"}) {
19941 exitStatus("Error", "can't compare headers with $SLIB_TYPE libraries");
19942 }
19943 elsif(not $Descriptor{1}{"Headers"} and $Descriptor{1}{"Libs"}
19944 and $Descriptor{2}{"Headers"} and not $Descriptor{2}{"Libs"}) {
19945 exitStatus("Error", "can't compare $SLIB_TYPE libraries with headers");
19946 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040019947 if(not $Descriptor{1}{"Headers"})
19948 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019949 if($CheckHeadersOnly_Opt) {
19950 exitStatus("Error", "can't find header files info in descriptor d1");
19951 }
19952 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040019953 if(not $Descriptor{2}{"Headers"})
19954 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019955 if($CheckHeadersOnly_Opt) {
19956 exitStatus("Error", "can't find header files info in descriptor d2");
19957 }
19958 }
19959 if(not $Descriptor{1}{"Headers"}
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040019960 or not $Descriptor{2}{"Headers"})
19961 {
19962 if(not $CheckObjectsOnly_Opt)
19963 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019964 printMsg("WARNING", "comparing $SLIB_TYPE libraries only");
19965 $CheckObjectsOnly = 1;
19966 }
19967 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040019968 if(not $Descriptor{1}{"Libs"})
19969 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019970 if($CheckObjectsOnly_Opt) {
19971 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d1");
19972 }
19973 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040019974 if(not $Descriptor{2}{"Libs"})
19975 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019976 if($CheckObjectsOnly_Opt) {
19977 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d2");
19978 }
19979 }
19980 if(not $Descriptor{1}{"Libs"}
19981 or not $Descriptor{2}{"Libs"})
19982 { # comparing standalone header files
19983 # comparing ABI dumps created with --headers-only
19984 if(not $CheckHeadersOnly_Opt)
19985 {
19986 printMsg("WARNING", "checking headers only");
19987 $CheckHeadersOnly = 1;
19988 }
19989 }
19990 if($UseDumps)
19991 { # --use-dumps
19992 # parallel processing
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019993 my $DumpPath1 = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{1}{"Version"}.".abi.$AR_EXT";
19994 my $DumpPath2 = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{2}{"Version"}.".abi.$AR_EXT";
19995
19996 unlink($DumpPath1);
19997 unlink($DumpPath2);
19998
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019999 my $pid = fork();
20000 if($pid)
20001 { # dump on two CPU cores
20002 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
20003 if($RelativeDirectory{1}) {
20004 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
20005 }
20006 if($OutputLogPath{1}) {
20007 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
20008 }
20009 if($CrossGcc) {
20010 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
20011 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020012 if($Quiet)
20013 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020014 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020015 @PARAMS = (@PARAMS, "-logging-mode", "a");
20016 }
20017 elsif($LogMode and $LogMode ne "w")
20018 { # "w" is default
20019 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020020 }
20021 if($ExtendedCheck) {
20022 @PARAMS = (@PARAMS, "-extended");
20023 }
20024 if($UserLang) {
20025 @PARAMS = (@PARAMS, "-lang", $UserLang);
20026 }
20027 if($TargetVersion{1}) {
20028 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
20029 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020030 if($BinaryOnly) {
20031 @PARAMS = (@PARAMS, "-binary");
20032 }
20033 if($SourceOnly) {
20034 @PARAMS = (@PARAMS, "-source");
20035 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020036 if($SortDump) {
20037 @PARAMS = (@PARAMS, "-sort");
20038 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020039 if($DumpFormat and $DumpFormat ne "perl") {
20040 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
20041 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020042 if($CheckHeadersOnly) {
20043 @PARAMS = (@PARAMS, "-headers-only");
20044 }
20045 if($CheckObjectsOnly) {
20046 @PARAMS = (@PARAMS, "-objects-only");
20047 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020048 if($Debug)
20049 {
20050 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020051 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020052 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020053 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020054 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020055 exit(1);
20056 }
20057 }
20058 else
20059 { # child
20060 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
20061 if($RelativeDirectory{2}) {
20062 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
20063 }
20064 if($OutputLogPath{2}) {
20065 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
20066 }
20067 if($CrossGcc) {
20068 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
20069 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020070 if($Quiet)
20071 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020072 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020073 @PARAMS = (@PARAMS, "-logging-mode", "a");
20074 }
20075 elsif($LogMode and $LogMode ne "w")
20076 { # "w" is default
20077 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020078 }
20079 if($ExtendedCheck) {
20080 @PARAMS = (@PARAMS, "-extended");
20081 }
20082 if($UserLang) {
20083 @PARAMS = (@PARAMS, "-lang", $UserLang);
20084 }
20085 if($TargetVersion{2}) {
20086 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
20087 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020088 if($BinaryOnly) {
20089 @PARAMS = (@PARAMS, "-binary");
20090 }
20091 if($SourceOnly) {
20092 @PARAMS = (@PARAMS, "-source");
20093 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020094 if($SortDump) {
20095 @PARAMS = (@PARAMS, "-sort");
20096 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020097 if($DumpFormat and $DumpFormat ne "perl") {
20098 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
20099 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020100 if($CheckHeadersOnly) {
20101 @PARAMS = (@PARAMS, "-headers-only");
20102 }
20103 if($CheckObjectsOnly) {
20104 @PARAMS = (@PARAMS, "-objects-only");
20105 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020106 if($Debug)
20107 {
20108 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020109 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020110 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020111 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020112 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020113 exit(1);
20114 }
20115 else {
20116 exit(0);
20117 }
20118 }
20119 waitpid($pid, 0);
20120 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020121 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
20122 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020123 if($TargetLibraryFName ne $TargetLibraryName) {
20124 @CMP_PARAMS = (@CMP_PARAMS, "-l-full", $TargetLibraryFName);
20125 }
20126 if($ShowRetVal) {
20127 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
20128 }
20129 if($CrossGcc) {
20130 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
20131 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040020132 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
20133 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020134 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020135 }
20136 if($ReportFormat and $ReportFormat ne "html")
20137 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020138 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
20139 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020140 if($OutputReportPath) {
20141 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
20142 }
20143 if($BinaryReportPath) {
20144 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
20145 }
20146 if($SourceReportPath) {
20147 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
20148 }
20149 if($LoggingPath) {
20150 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
20151 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020152 if($CheckHeadersOnly) {
20153 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
20154 }
20155 if($CheckObjectsOnly) {
20156 @CMP_PARAMS = (@CMP_PARAMS, "-objects-only");
20157 }
20158 if($BinaryOnly) {
20159 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
20160 }
20161 if($SourceOnly) {
20162 @CMP_PARAMS = (@CMP_PARAMS, "-source");
20163 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020164 if($Browse) {
20165 @CMP_PARAMS = (@CMP_PARAMS, "-browse", $Browse);
20166 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020167 if($OpenReport) {
20168 @CMP_PARAMS = (@CMP_PARAMS, "-open");
20169 }
20170 if($Debug)
20171 {
20172 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
20173 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020174 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020175 system("perl", $0, @CMP_PARAMS);
20176 exit($?>>8);
20177 }
20178 if(not $Descriptor{1}{"Dump"}
20179 or not $Descriptor{2}{"Dump"})
20180 { # need GCC toolchain to analyze
20181 # header files and libraries
20182 detect_default_paths("inc|lib|gcc");
20183 }
20184 if(not $Descriptor{1}{"Dump"})
20185 {
20186 if(not $CheckHeadersOnly) {
20187 readLibs(1);
20188 }
20189 if($CheckHeadersOnly) {
20190 setLanguage(1, "C++");
20191 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020192 if(not $CheckObjectsOnly) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020193 searchForHeaders(1);
20194 }
20195 $WORD_SIZE{1} = detectWordSize();
20196 }
20197 if(not $Descriptor{2}{"Dump"})
20198 {
20199 if(not $CheckHeadersOnly) {
20200 readLibs(2);
20201 }
20202 if($CheckHeadersOnly) {
20203 setLanguage(2, "C++");
20204 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020205 if(not $CheckObjectsOnly) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020206 searchForHeaders(2);
20207 }
20208 $WORD_SIZE{2} = detectWordSize();
20209 }
20210 if($WORD_SIZE{1} ne $WORD_SIZE{2})
20211 { # support for old ABI dumps
20212 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020213 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020214 {
20215 $WORD_SIZE{1} = $WORD_SIZE{2};
20216 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
20217 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020218 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020219 {
20220 $WORD_SIZE{2} = $WORD_SIZE{1};
20221 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
20222 }
20223 }
20224 elsif(not $WORD_SIZE{1}
20225 and not $WORD_SIZE{2})
20226 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020227 $WORD_SIZE{1} = "4";
20228 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020229 }
20230 if($Descriptor{1}{"Dump"})
20231 { # support for old ABI dumps
20232 prepareTypes(1);
20233 }
20234 if($Descriptor{2}{"Dump"})
20235 { # support for old ABI dumps
20236 prepareTypes(2);
20237 }
20238 if($AppPath and not keys(%{$Symbol_Library{1}})) {
20239 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
20240 }
20241 # started to process input data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020242 if(not $CheckObjectsOnly)
20243 {
20244 if($Descriptor{1}{"Headers"}
20245 and not $Descriptor{1}{"Dump"}) {
20246 readHeaders(1);
20247 }
20248 if($Descriptor{2}{"Headers"}
20249 and not $Descriptor{2}{"Dump"}) {
20250 readHeaders(2);
20251 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020252 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020253
20254 # clean memory
20255 %SystemHeaders = ();
20256 %mangled_name_gcc = ();
20257
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020258 prepareSymbols(1);
20259 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020260
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020261 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020262 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020263
20264 # Virtual Tables
20265 registerVTable(1);
20266 registerVTable(2);
20267
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020268 if(not checkDump(1, "1.22")
20269 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020270 { # support for old ABI dumps
20271 foreach my $ClassName (keys(%{$VirtualTable{2}}))
20272 {
20273 if($ClassName=~/</)
20274 { # templates
20275 if(not defined $VirtualTable{1}{$ClassName})
20276 { # synchronize
20277 delete($VirtualTable{2}{$ClassName});
20278 }
20279 }
20280 }
20281 }
20282
20283 registerOverriding(1);
20284 registerOverriding(2);
20285
20286 setVirtFuncPositions(1);
20287 setVirtFuncPositions(2);
20288
20289 # Other
20290 addParamNames(1);
20291 addParamNames(2);
20292
20293 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020294}
20295
20296sub compareAPIs($)
20297{
20298 my $Level = $_[0];
20299 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020300 loadModule("CallConv");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020301 if($Level eq "Binary") {
20302 printMsg("INFO", "comparing ABIs ...");
20303 }
20304 else {
20305 printMsg("INFO", "comparing APIs ...");
20306 }
20307 if($CheckHeadersOnly
20308 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020309 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020310 detectAdded_H($Level);
20311 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020312 }
20313 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020314 { # added/removed in libs
20315 detectAdded($Level);
20316 detectRemoved($Level);
20317 }
20318 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020319 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020320 mergeSignatures($Level);
20321 if(keys(%{$CheckedSymbols{$Level}})) {
20322 mergeConstants($Level);
20323 }
20324 }
20325 if($CheckHeadersOnly
20326 or $Level eq "Source")
20327 { # added/removed in headers
20328 mergeHeaders($Level);
20329 }
20330 else
20331 { # added/removed in libs
20332 mergeLibs($Level);
20333 if($CheckImpl
20334 and $Level eq "Binary") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020335 mergeImpl();
20336 }
20337 }
20338}
20339
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020340sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020341{
20342 my %Opts = (
20343 "OStarget"=>$OStarget,
20344 "Debug"=>$Debug,
20345 "Quiet"=>$Quiet,
20346 "LogMode"=>$LogMode,
20347 "CheckHeadersOnly"=>$CheckHeadersOnly,
20348
20349 "SystemRoot"=>$SystemRoot,
20350 "MODULES_DIR"=>$MODULES_DIR,
20351 "GCC_PATH"=>$GCC_PATH,
20352 "TargetSysInfo"=>$TargetSysInfo,
20353 "CrossPrefix"=>$CrossPrefix,
20354 "TargetLibraryName"=>$TargetLibraryName,
20355 "CrossGcc"=>$CrossGcc,
20356 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020357 "NoStdInc"=>$NoStdInc,
20358
20359 "BinaryOnly" => $BinaryOnly,
20360 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020361 );
20362 return \%Opts;
20363}
20364
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020365sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020366{
20367 my %CODE_ERROR = reverse(%ERROR_CODE);
20368 return $CODE_ERROR{$_[0]};
20369}
20370
20371sub scenario()
20372{
20373 if($StdOut)
20374 { # enable quiet mode
20375 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020376 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020377 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020378 if(not $LogMode)
20379 { # default
20380 $LogMode = "w";
20381 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020382 if($UserLang)
20383 { # --lang=C++
20384 $UserLang = uc($UserLang);
20385 $COMMON_LANGUAGE{1}=$UserLang;
20386 $COMMON_LANGUAGE{2}=$UserLang;
20387 }
20388 if($LoggingPath)
20389 {
20390 $OutputLogPath{1} = $LoggingPath;
20391 $OutputLogPath{2} = $LoggingPath;
20392 if($Quiet) {
20393 $COMMON_LOG_PATH = $LoggingPath;
20394 }
20395 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020396 if($OutputDumpPath)
20397 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020398 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020399 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
20400 }
20401 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020402 if($BinaryOnly and $SourceOnly)
20403 { # both --binary and --source
20404 # is the default mode
20405 $DoubleReport = 1;
20406 $JoinReport = 0;
20407 $BinaryOnly = 0;
20408 $SourceOnly = 0;
20409 if($OutputReportPath)
20410 { # --report-path
20411 $DoubleReport = 0;
20412 $JoinReport = 1;
20413 }
20414 }
20415 elsif($BinaryOnly or $SourceOnly)
20416 { # --binary or --source
20417 $DoubleReport = 0;
20418 $JoinReport = 0;
20419 }
20420 if($UseXML)
20421 { # --xml option
20422 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020423 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020424 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020425 if($ReportFormat)
20426 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020427 $ReportFormat = lc($ReportFormat);
20428 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020429 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020430 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020431 if($ReportFormat eq "htm")
20432 { # HTM == HTML
20433 $ReportFormat = "html";
20434 }
20435 elsif($ReportFormat eq "xml")
20436 { # --report-format=XML equal to --xml
20437 $UseXML = 1;
20438 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020439 }
20440 else
20441 { # default: HTML
20442 $ReportFormat = "html";
20443 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020444 if($DumpFormat)
20445 { # validate
20446 $DumpFormat = lc($DumpFormat);
20447 if($DumpFormat!~/\A(xml|perl)\Z/) {
20448 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
20449 }
20450 if($DumpFormat eq "xml")
20451 { # --dump-format=XML equal to --xml
20452 $UseXML = 1;
20453 }
20454 }
20455 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020456 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020457 $DumpFormat = "perl";
20458 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020459 if($Quiet and $LogMode!~/a|n/)
20460 { # --quiet log
20461 if(-f $COMMON_LOG_PATH) {
20462 unlink($COMMON_LOG_PATH);
20463 }
20464 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020465 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020466 $CheckUndefined = 1;
20467 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020468 if($TestTool and $UseDumps)
20469 { # --test && --use-dumps == --test-dump
20470 $TestDump = 1;
20471 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020472 if($Help)
20473 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020474 HELP_MESSAGE();
20475 exit(0);
20476 }
20477 if($InfoMsg) {
20478 INFO_MESSAGE();
20479 exit(0);
20480 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020481 if($ShowVersion)
20482 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020483 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.");
20484 exit(0);
20485 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020486 if($DumpVersion)
20487 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020488 printMsg("INFO", $TOOL_VERSION);
20489 exit(0);
20490 }
20491 if($ExtendedCheck) {
20492 $CheckHeadersOnly = 1;
20493 }
20494 if($SystemRoot_Opt)
20495 { # user defined root
20496 if(not -e $SystemRoot_Opt) {
20497 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
20498 }
20499 $SystemRoot = $SystemRoot_Opt;
20500 $SystemRoot=~s/[\/]+\Z//g;
20501 if($SystemRoot) {
20502 $SystemRoot = get_abs_path($SystemRoot);
20503 }
20504 }
20505 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040020506
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020507 if($SortDump)
20508 {
20509 $Data::Dumper::Useperl = 1;
20510 $Data::Dumper::Sortkeys = \&dump_sorting;
20511 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040020512
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020513 if($TargetLibsPath)
20514 {
20515 if(not -f $TargetLibsPath) {
20516 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
20517 }
20518 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath))) {
20519 $TargetLibs{$Lib} = 1;
20520 }
20521 }
20522 if($TargetHeadersPath)
20523 { # --headers-list
20524 if(not -f $TargetHeadersPath) {
20525 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
20526 }
20527 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
20528 {
20529 $TargetHeaders{1}{$Header} = 1;
20530 $TargetHeaders{2}{$Header} = 1;
20531 }
20532 }
20533 if($TargetHeader)
20534 { # --header
20535 $TargetHeaders{1}{$TargetHeader} = 1;
20536 $TargetHeaders{2}{$TargetHeader} = 1;
20537 }
20538 if($TestTool
20539 or $TestDump)
20540 { # --test, --test-dump
20541 detect_default_paths("bin|gcc"); # to compile libs
20542 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020543 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
20544 $LIB_EXT, $GCC_PATH, $Browse, $OpenReport, $SortDump, $CheckHeadersOnly, $CheckObjectsOnly);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020545 exit(0);
20546 }
20547 if($DumpSystem)
20548 { # --dump-system
20549 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020550 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020551 { # system XML descriptor
20552 if(not -f $DumpSystem) {
20553 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
20554 }
20555 my $Ret = readSystemDescriptor(readFile($DumpSystem));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020556 foreach (@{$Ret->{"Tools"}})
20557 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020558 push_U($SystemPaths{"bin"}, $_);
20559 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020560 }
20561 if($Ret->{"CrossPrefix"}) {
20562 $CrossPrefix = $Ret->{"CrossPrefix"};
20563 }
20564 }
20565 elsif($SystemRoot_Opt)
20566 { # -sysroot "/" option
20567 # default target: /usr/lib, /usr/include
20568 # search libs: /usr/lib and /lib
20569 if(not -e $SystemRoot."/usr/lib") {
20570 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
20571 }
20572 if(not -e $SystemRoot."/lib") {
20573 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
20574 }
20575 if(not -e $SystemRoot."/usr/include") {
20576 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
20577 }
20578 readSystemDescriptor("
20579 <name>
20580 $DumpSystem
20581 </name>
20582 <headers>
20583 $SystemRoot/usr/include
20584 </headers>
20585 <libs>
20586 $SystemRoot/usr/lib
20587 </libs>
20588 <search_libs>
20589 $SystemRoot/lib
20590 </search_libs>");
20591 }
20592 else {
20593 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
20594 }
20595 detect_default_paths("bin|gcc"); # to check symbols
20596 if($OStarget eq "windows")
20597 { # to run dumpbin.exe
20598 # and undname.exe
20599 check_win32_env();
20600 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020601 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020602 exit(0);
20603 }
20604 if($CmpSystems)
20605 { # --cmp-systems
20606 detect_default_paths("bin"); # to extract dumps
20607 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020608 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020609 exit(0);
20610 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020611 if($GenerateTemplate)
20612 {
20613 writeFile("VERSION.xml", $DescriptorTemplate."\n");
20614 printMsg("INFO", "XML-descriptor template ./VERSION.xml has been generated");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020615 exit(0);
20616 }
20617 if(not $TargetLibraryName) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020618 exitStatus("Error", "library name is not selected (-l option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020619 }
20620 else
20621 { # validate library name
20622 if($TargetLibraryName=~/[\*\/\\]/) {
20623 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
20624 }
20625 }
20626 if(not $TargetLibraryFName) {
20627 $TargetLibraryFName = $TargetLibraryName;
20628 }
20629 if($CheckHeadersOnly_Opt and $CheckObjectsOnly_Opt) {
20630 exitStatus("Error", "you can't specify both -headers-only and -objects-only options at the same time");
20631 }
20632 if($SymbolsListPath)
20633 {
20634 if(not -f $SymbolsListPath) {
20635 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
20636 }
20637 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
20638 $SymbolsList{$Interface} = 1;
20639 }
20640 }
20641 if($SkipHeadersPath)
20642 {
20643 if(not -f $SkipHeadersPath) {
20644 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
20645 }
20646 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020647 { # register for both versions
20648 $SkipHeadersList{1}{$Path} = 1;
20649 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020650 my ($CPath, $Type) = classifyPath($Path);
20651 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020652 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020653 }
20654 }
20655 if($ParamNamesPath)
20656 {
20657 if(not -f $ParamNamesPath) {
20658 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
20659 }
20660 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
20661 {
20662 if($Line=~s/\A(\w+)\;//)
20663 {
20664 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020665 if($Line=~/;(\d+);/)
20666 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020667 while($Line=~s/(\d+);(\w+)//) {
20668 $AddIntParams{$Interface}{$1}=$2;
20669 }
20670 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020671 else
20672 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020673 my $Num = 0;
20674 foreach my $Name (split(/;/, $Line)) {
20675 $AddIntParams{$Interface}{$Num++}=$Name;
20676 }
20677 }
20678 }
20679 }
20680 }
20681 if($AppPath)
20682 {
20683 if(not -f $AppPath) {
20684 exitStatus("Access_Error", "can't access file \'$AppPath\'");
20685 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020686 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020687 $SymbolsList_App{$Interface} = 1;
20688 }
20689 }
20690 if($DumpAPI)
20691 { # --dump-abi
20692 # make an API dump
20693 create_ABI_Dump();
20694 exit($COMPILE_ERRORS);
20695 }
20696 # default: compare APIs
20697 # -d1 <path>
20698 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020699 compareInit();
20700 if($JoinReport or $DoubleReport)
20701 {
20702 compareAPIs("Binary");
20703 compareAPIs("Source");
20704 }
20705 elsif($BinaryOnly) {
20706 compareAPIs("Binary");
20707 }
20708 elsif($SourceOnly) {
20709 compareAPIs("Source");
20710 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020711 exitReport();
20712}
20713
20714scenario();