blob: f5606e90e26f44129c93f8444bf98a4c4c559f99 [file] [log] [blame]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001#!/usr/bin/perl
2###########################################################################
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003# ABI Compliance Checker (ACC) 1.99
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004# A tool for checking backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005#
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006# Copyright (C) 2009-2010 The Linux Foundation
7# Copyright (C) 2009-2011 Institute for System Programming, RAS
8# Copyright (C) 2011-2012 Nokia Corporation and/or its subsidiary(-ies)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009# Copyright (C) 2011-2013 ROSA Laboratory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010#
11# Written by Andrey Ponomarenko
12#
13# PLATFORMS
14# =========
15# Linux, FreeBSD, Mac OS X, Haiku, MS Windows, Symbian
16#
17# REQUIREMENTS
18# ============
19# Linux
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040020# - G++ (3.0-4.7, recommended 4.5 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021# - GNU Binutils (readelf, c++filt, objdump)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022# - Perl 5 (5.8 or newer)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040023# - Ctags (5.8 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040024#
25# Mac OS X
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040026# - Xcode (g++, c++filt, otool, nm)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040027# - Ctags (5.8 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040028#
29# MS Windows
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040030# - MinGW (3.0-4.7, recommended 4.5 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040031# - MS Visual C++ (dumpbin, undname, cl)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040032# - Active Perl 5 (5.8 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040033# - Sigcheck v1.71 or newer
34# - Info-ZIP 3.0 (zip, unzip)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040035# - Ctags (5.8 or newer)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040036# - Add tool locations to the PATH environment variable
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040037# - Run vsvars32.bat (C:\Microsoft Visual Studio 9.0\Common7\Tools\)
38#
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 Ponomarenkoab282102012-03-11 11:57:02 +040060
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040061my $TOOL_VERSION = "1.99";
62my $ABI_DUMP_VERSION = "3.0";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040063my $OLDEST_SUPPORTED_VERSION = "1.18";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040064my $XML_REPORT_VERSION = "1.1";
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040065my $XML_ABI_DUMP_VERSION = "1.2";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040066my $OSgroup = get_OSgroup();
67my $ORIG_DIR = cwd();
68my $TMP_DIR = tempdir(CLEANUP=>1);
69
70# Internal modules
71my $MODULES_DIR = get_Modules();
72push(@INC, get_dirname($MODULES_DIR));
73# Rules DB
74my %RULES_PATH = (
75 "Binary" => $MODULES_DIR."/RulesBin.xml",
76 "Source" => $MODULES_DIR."/RulesSrc.xml");
77
78my ($Help, $ShowVersion, %Descriptor, $TargetLibraryName, $GenerateTemplate,
79$TestTool, $DumpAPI, $SymbolsListPath, $CheckHeadersOnly_Opt, $UseDumps,
80$CheckObjectsOnly_Opt, $AppPath, $StrictCompat, $DumpVersion, $ParamNamesPath,
81%RelativeDirectory, $TargetLibraryFName, $TestDump, $CheckImpl, $LoggingPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040082%TargetVersion, $InfoMsg, $UseOldDumps, $CrossGcc, %OutputLogPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040083$OutputReportPath, $OutputDumpPath, $ShowRetVal, $SystemRoot_Opt, $DumpSystem,
84$CmpSystems, $TargetLibsPath, $Debug, $CrossPrefix, $UseStaticLibs, $NoStdInc,
85$TargetComponent_Opt, $TargetSysInfo, $TargetHeader, $ExtendedCheck, $Quiet,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040086$SkipHeadersPath, $CppCompat, $LogMode, $StdOut, $ListAffected, $ReportFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040087$UserLang, $TargetHeadersPath, $BinaryOnly, $SourceOnly, $BinaryReportPath,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040088$SourceReportPath, $UseXML, $Browse, $OpenReport, $SortDump, $DumpFormat,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040089$ExtraInfo, $ExtraDump, $Force, $Tolerance, $Tolerant, $SkipSymbolsListPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040090
91my $CmdName = get_filename($0);
92my %OS_LibExt = (
93 "dynamic" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040094 "linux"=>"so",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040095 "macos"=>"dylib",
96 "windows"=>"dll",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040097 "symbian"=>"dso",
98 "default"=>"so"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040099 },
100 "static" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400101 "linux"=>"a",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400102 "windows"=>"lib",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400103 "symbian"=>"lib",
104 "default"=>"a"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400105 }
106);
107
108my %OS_Archive = (
109 "windows"=>"zip",
110 "default"=>"tar.gz"
111);
112
113my %ERROR_CODE = (
114 # Compatible verdict
115 "Compatible"=>0,
116 "Success"=>0,
117 # Incompatible verdict
118 "Incompatible"=>1,
119 # Undifferentiated error code
120 "Error"=>2,
121 # System command is not found
122 "Not_Found"=>3,
123 # Cannot access input files
124 "Access_Error"=>4,
125 # Cannot compile header files
126 "Cannot_Compile"=>5,
127 # Header compiled with errors
128 "Compile_Error"=>6,
129 # Invalid input ABI dump
130 "Invalid_Dump"=>7,
131 # Incompatible version of ABI dump
132 "Dump_Version"=>8,
133 # Cannot find a module
134 "Module_Error"=>9,
135 # Empty intersection between
136 # headers and shared objects
137 "Empty_Intersection"=>10,
138 # Empty set of symbols in headers
139 "Empty_Set"=>11
140);
141
142my %HomePage = (
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400143 "Wiki"=>"http://ispras.linuxbase.org/index.php/ABI_compliance_checker",
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400144 "Dev1"=>"https://github.com/lvc/abi-compliance-checker",
145 "Dev2"=>"http://forge.ispras.ru/projects/abi-compliance-checker"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400146);
147
148my $ShortUsage = "ABI Compliance Checker (ACC) $TOOL_VERSION
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400149A tool for checking backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400150Copyright (C) 2012 ROSA Laboratory
151License: GNU LGPL or GNU GPL
152
153Usage: $CmdName [options]
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400154Example: $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400155
156OLD.xml and NEW.xml are XML-descriptors:
157
158 <version>
159 1.0
160 </version>
161
162 <headers>
163 /path/to/headers/
164 </headers>
165
166 <libs>
167 /path/to/libraries/
168 </libs>
169
170More info: $CmdName --help\n";
171
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400172if($#ARGV==-1)
173{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400174 printMsg("INFO", $ShortUsage);
175 exit(0);
176}
177
178foreach (2 .. $#ARGV)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400179{ # correct comma separated options
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400180 if($ARGV[$_-1] eq ",")
181 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400182 $ARGV[$_-2].=",".$ARGV[$_];
183 splice(@ARGV, $_-1, 2);
184 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400185 elsif($ARGV[$_-1]=~/,\Z/)
186 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400187 $ARGV[$_-1].=$ARGV[$_];
188 splice(@ARGV, $_, 1);
189 }
190 elsif($ARGV[$_]=~/\A,/
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400191 and $ARGV[$_] ne ",")
192 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400193 $ARGV[$_-1].=$ARGV[$_];
194 splice(@ARGV, $_, 1);
195 }
196}
197
198GetOptions("h|help!" => \$Help,
199 "i|info!" => \$InfoMsg,
200 "v|version!" => \$ShowVersion,
201 "dumpversion!" => \$DumpVersion,
202# general options
203 "l|lib|library=s" => \$TargetLibraryName,
204 "d1|old|o=s" => \$Descriptor{1}{"Path"},
205 "d2|new|n=s" => \$Descriptor{2}{"Path"},
206 "dump|dump-abi|dump_abi=s" => \$DumpAPI,
207 "old-dumps!" => \$UseOldDumps,
208# extra options
209 "d|descriptor-template!" => \$GenerateTemplate,
210 "app|application=s" => \$AppPath,
211 "static-libs!" => \$UseStaticLibs,
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +0400212 "cross-gcc|gcc-path=s" => \$CrossGcc,
213 "cross-prefix|gcc-prefix=s" => \$CrossPrefix,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400214 "sysroot=s" => \$SystemRoot_Opt,
215 "v1|version1|vnum=s" => \$TargetVersion{1},
216 "v2|version2=s" => \$TargetVersion{2},
217 "s|strict!" => \$StrictCompat,
218 "symbols-list=s" => \$SymbolsListPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400219 "skip-symbols=s" => \$SkipSymbolsListPath,
220 "headers-list=s" => \$TargetHeadersPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400221 "skip-headers=s" => \$SkipHeadersPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400222 "header=s" => \$TargetHeader,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400223 "headers-only|headers_only!" => \$CheckHeadersOnly_Opt,
224 "objects-only!" => \$CheckObjectsOnly_Opt,
225 "check-impl|check-implementation!" => \$CheckImpl,
226 "show-retval!" => \$ShowRetVal,
227 "use-dumps!" => \$UseDumps,
228 "nostdinc!" => \$NoStdInc,
229 "dump-system=s" => \$DumpSystem,
230 "sysinfo=s" => \$TargetSysInfo,
231 "cmp-systems!" => \$CmpSystems,
232 "libs-list=s" => \$TargetLibsPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400233 "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,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400266 "force!" => \$Force,
267 "tolerance=s" => \$Tolerance,
268 "tolerant!" => \$Tolerant
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400269) or ERR_MESSAGE();
270
271sub ERR_MESSAGE()
272{
273 printMsg("INFO", "\n".$ShortUsage);
274 exit($ERROR_CODE{"Error"});
275}
276
277my $LIB_TYPE = $UseStaticLibs?"static":"dynamic";
278my $SLIB_TYPE = $LIB_TYPE;
279if($OSgroup!~/macos|windows/ and $SLIB_TYPE eq "dynamic")
280{ # show as "shared" library
281 $SLIB_TYPE = "shared";
282}
283my $LIB_EXT = getLIB_EXT($OSgroup);
284my $AR_EXT = getAR_EXT($OSgroup);
285my $BYTE_SIZE = 8;
286my $COMMON_LOG_PATH = "logs/run.log";
287
288my $HelpMessage="
289NAME:
290 ABI Compliance Checker ($CmdName)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400291 Check backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400292
293DESCRIPTION:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400294 ABI Compliance Checker (ACC) is a tool for checking backward binary and
295 source-level compatibility of a $SLIB_TYPE C/C++ library. The tool checks
296 header files and $SLIB_TYPE libraries (*.$LIB_EXT) of old and new versions and
297 analyzes changes in API and ABI (ABI=API+compiler ABI) that may break binary
298 and/or source-level compatibility: changes in calling stack, v-table changes,
299 removed symbols, renamed fields, etc. Binary incompatibility may result in
300 crashing or incorrect behavior of applications built with an old version of
301 a library if they run on a new one. Source incompatibility may result in
302 recompilation errors with a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400303
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400304 The tool is intended for developers of software libraries and maintainers
305 of operating systems who are interested in ensuring backward compatibility,
306 i.e. allow old applications to run or to be recompiled with newer library
307 versions.
308
309 Also the tool can be used by ISVs for checking applications portability to
310 new library versions. Found issues can be taken into account when adapting
311 the application to a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400312
313 This tool is free software: you can redistribute it and/or modify it
314 under the terms of the GNU LGPL or GNU GPL.
315
316USAGE:
317 $CmdName [options]
318
319EXAMPLE:
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400320 $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400321
322 OLD.xml and NEW.xml are XML-descriptors:
323
324 <version>
325 1.0
326 </version>
327
328 <headers>
329 /path1/to/header(s)/
330 /path2/to/header(s)/
331 ...
332 </headers>
333
334 <libs>
335 /path1/to/library(ies)/
336 /path2/to/library(ies)/
337 ...
338 </libs>
339
340INFORMATION OPTIONS:
341 -h|-help
342 Print this help.
343
344 -i|-info
345 Print complete info.
346
347 -v|-version
348 Print version information.
349
350 -dumpversion
351 Print the tool version ($TOOL_VERSION) and don't do anything else.
352
353GENERAL OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400354 -l|-lib|-library NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400355 Library name (without version).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400356
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400357 -d1|-old|-o PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400358 Descriptor of 1st (old) library version.
359 It may be one of the following:
360
361 1. XML-descriptor (VERSION.xml file):
362
363 <version>
364 1.0
365 </version>
366
367 <headers>
368 /path1/to/header(s)/
369 /path2/to/header(s)/
370 ...
371 </headers>
372
373 <libs>
374 /path1/to/library(ies)/
375 /path2/to/library(ies)/
376 ...
377 </libs>
378
379 ... (XML-descriptor template
380 can be generated by -d option)
381
382 2. ABI dump generated by -dump option
383 3. Directory with headers and/or $SLIB_TYPE libraries
384 4. Single header file
385 5. Single $SLIB_TYPE library
386 6. Comma separated list of headers and/or libraries
387
388 If you are using an 2-6 descriptor types then you should
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400389 specify version numbers with -v1 and -v2 options too.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400390
391 For more information, please see:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400392 http://ispras.linuxbase.org/index.php/Library_Descriptor
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400393
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400394 -d2|-new|-n PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400395 Descriptor of 2nd (new) library version.
396
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400397 -dump|-dump-abi PATH
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400398 Create library ABI dump for the input XML descriptor. You can
399 transfer it anywhere and pass instead of the descriptor. Also
400 it can be used for debugging the tool.
401
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400402 Supported ABI dump versions: 2.0<=V<=$ABI_DUMP_VERSION
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400403
404 -old-dumps
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400405 Enable support for old-version ABI dumps ($OLDEST_SUPPORTED_VERSION<=V<2.0).\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400406
407sub HELP_MESSAGE() {
408 printMsg("INFO", $HelpMessage."
409MORE INFO:
410 $CmdName --info\n");
411}
412
413sub INFO_MESSAGE()
414{
415 printMsg("INFO", "$HelpMessage
416EXTRA OPTIONS:
417 -d|-descriptor-template
418 Create XML-descriptor template ./VERSION.xml
419
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400420 -app|-application PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400421 This option allows to specify the application that should be checked
422 for portability to the new library version.
423
424 -static-libs
425 Check static libraries instead of the shared ones. The <libs> section
426 of the XML-descriptor should point to static libraries location.
427
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400428 -cross-gcc|-gcc-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400429 Path to the cross GCC compiler to use instead of the usual (host) GCC.
430
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400431 -cross-prefix|-gcc-prefix PREFIX
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400432 GCC toolchain prefix.
433
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400434 -sysroot DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400435 Specify the alternative root directory. The tool will search for include
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400436 paths in the DIR/usr/include and DIR/usr/lib directories.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400437
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400438 -v1|-version1 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400439 Specify 1st library version outside the descriptor. This option is needed
440 if you have prefered an alternative descriptor type (see -d1 option).
441
442 In general case you should specify it in the XML-descriptor:
443 <version>
444 VERSION
445 </version>
446
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400447 -v2|-version2 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400448 Specify 2nd library version outside the descriptor.
449
450 -s|-strict
451 Treat all compatibility warnings as problems. Add a number of \"Low\"
452 severity problems to the return value of the tool.
453
454 -headers-only
455 Check header files without $SLIB_TYPE libraries. It is easy to run, but may
456 provide a low quality compatibility report with false positives and
457 without detecting of added/removed symbols.
458
459 Alternatively you can write \"none\" word to the <libs> section
460 in the XML-descriptor:
461 <libs>
462 none
463 </libs>
464
465 -objects-only
466 Check $SLIB_TYPE libraries without header files. It is easy to run, but may
467 provide a low quality compatibility report with false positives and
468 without analysis of changes in parameters and data types.
469
470 Alternatively you can write \"none\" word to the <headers> section
471 in the XML-descriptor:
472 <headers>
473 none
474 </headers>
475
476 -check-impl|-check-implementation
477 Compare canonified disassembled binary code of $SLIB_TYPE libraries to
478 detect changes in the implementation. Add \'Problems with Implementation\'
479 section to the report.
480
481 -show-retval
482 Show the symbol's return type in the report.
483
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400484 -symbols-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400485 This option allows to specify a file with a list of symbols (mangled
486 names in C++) that should be checked, other symbols will not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400487
488 -skip-symbols PATH
489 The list of symbols that should NOT be checked.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400490
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400491 -headers-list PATH
492 The file with a list of headers, that should be checked/dumped.
493
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400494 -skip-headers PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400495 The file with the list of header files, that should not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400496
497 -header NAME
498 Check/Dump ABI of this header only.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400499
500 -use-dumps
501 Make dumps for two versions of a library and compare dumps. This should
502 increase the performance of the tool and decrease the system memory usage.
503
504 -nostdinc
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400505 Do not search in GCC standard system directories for header files.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400506
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400507 -dump-system NAME -sysroot DIR
508 Find all the shared libraries and header files in DIR directory,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400509 create XML descriptors and make ABI dumps for each library. The result
510 set of ABI dumps can be compared (--cmp-systems) with the other one
511 created for other version of operating system in order to check them for
512 compatibility. Do not forget to specify -cross-gcc option if your target
513 system requires some specific version of GCC compiler (different from
514 the host GCC). The system ABI dump will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400515 sys_dumps/NAME/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400516
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400517 -dump-system DESCRIPTOR.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400518 The same as the previous option but takes an XML descriptor of the target
519 system as input, where you should describe it:
520
521 /* Primary sections */
522
523 <name>
524 /* Name of the system */
525 </name>
526
527 <headers>
528 /* The list of paths to header files and/or
529 directories with header files, one per line */
530 </headers>
531
532 <libs>
533 /* The list of paths to shared libraries and/or
534 directories with shared libraries, one per line */
535 </libs>
536
537 /* Optional sections */
538
539 <search_headers>
540 /* List of directories to be searched
541 for header files to automatically
542 generate include paths, one per line */
543 </search_headers>
544
545 <search_libs>
546 /* List of directories to be searched
547 for shared libraries to resolve
548 dependencies, one per line */
549 </search_libs>
550
551 <tools>
552 /* List of directories with tools used
553 for analysis (GCC toolchain), one per line */
554 </tools>
555
556 <cross_prefix>
557 /* GCC toolchain prefix.
558 Examples:
559 arm-linux-gnueabi
560 arm-none-symbianelf */
561 </cross_prefix>
562
563 <gcc_options>
564 /* Additional GCC options, one per line */
565 </gcc_options>
566
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400567 -sysinfo DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400568 This option may be used with -dump-system to dump ABI of operating
569 systems and configure the dumping process.
570 Default:
571 modules/Targets/{unix, symbian, windows}
572
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400573 -cmp-systems -d1 sys_dumps/NAME1/ARCH -d2 sys_dumps/NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400574 Compare two system ABI dumps. Create compatibility reports for each
575 library and the common HTML report including the summary of test
576 results for all checked libraries. Report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400577 sys_compat_reports/NAME1_to_NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400578
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400579 -libs-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400580 The file with a list of libraries, that should be dumped by
581 the -dump-system option or should be checked by the -cmp-systems option.
582
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400583 -ext|-extended
584 If your library A is supposed to be used by other library B and you
585 want to control the ABI of B, then you should enable this option. The
586 tool will check for changes in all data types, even if they are not
587 used by any function in the library A. Such data types are not part
588 of the A library ABI, but may be a part of the ABI of the B library.
589
590 The short scheme is:
591 app C (broken) -> lib B (broken ABI) -> lib A (stable ABI)
592
593 -q|-quiet
594 Print all messages to the file instead of stdout and stderr.
595 Default path (can be changed by -log-path option):
596 $COMMON_LOG_PATH
597
598 -stdout
599 Print analysis results (compatibility reports and ABI dumps) to stdout
600 instead of creating a file. This would allow piping data to other programs.
601
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400602 -report-format FMT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400603 Change format of compatibility report.
604 Formats:
605 htm - HTML format (default)
606 xml - XML format
607
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400608 -dump-format FMT
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400609 Change format of ABI dump.
610 Formats:
611 perl - Data::Dumper format (default)
612 xml - XML format
613
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400614 -xml
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400615 Alias for: --report-format=xml or --dump-format=xml
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400616
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400617 -lang LANG
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400618 Set library language (C or C++). You can use this option if the tool
619 cannot auto-detect a language. This option may be useful for checking
620 C-library headers (--lang=C) in --headers-only or --extended modes.
621
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400622 -binary|-bin|-abi
623 Show \"Binary\" compatibility problems only.
624 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400625 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400626
627 -source|-src|-api
628 Show \"Source\" compatibility problems only.
629 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400630 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400631
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400632OTHER OPTIONS:
633 -test
634 Run internal tests. Create two binary incompatible versions of a sample
635 library and run the tool to check them for compatibility. This option
636 allows to check if the tool works correctly in the current environment.
637
638 -test-dump
639 Test ability to create, read and compare ABI dumps.
640
641 -debug
642 Debugging mode. Print debug info on the screen. Save intermediate
643 analysis stages in the debug directory:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400644 debug/LIB_NAME/VERSION/
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400645
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400646 Also consider using --dump option for debugging the tool.
647
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400648 -cpp-compatible
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400649 If your header files are written in C language and can be compiled
650 by the G++ compiler (i.e. don't use C++ keywords), then you can tell
651 the tool about this and speedup the analysis.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400652
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400653 -p|-params PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400654 Path to file with the function parameter names. It can be used
655 for improving report view if the library header files have no
656 parameter names. File format:
657
658 func1;param1;param2;param3 ...
659 func2;param1;param2;param3 ...
660 ...
661
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400662 -relpath PATH
663 Replace {RELPATH} macros to PATH in the XML-descriptor used
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400664 for dumping the library ABI (see -dump option).
665
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400666 -relpath1 PATH
667 Replace {RELPATH} macros to PATH in the 1st XML-descriptor (-d1).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400668
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400669 -relpath2 PATH
670 Replace {RELPATH} macros to PATH in the 2nd XML-descriptor (-d2).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400671
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400672 -dump-path PATH
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400673 Specify a *.abi.$AR_EXT or *.abi file path where to generate an ABI dump.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400674 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400675 abi_dumps/LIB_NAME/LIB_NAME_VERSION.abi.$AR_EXT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400676
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400677 -sort
678 Enable sorting of data in ABI dumps.
679
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400680 -report-path PATH
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400681 Path to compatibility report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400682 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400683 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400684
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400685 -bin-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400686 Path to \"Binary\" compatibility report.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400687 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400688 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400689
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400690 -src-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400691 Path to \"Source\" compatibility report.
692 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400693 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400694
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400695 -log-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400696 Log path for all messages.
697 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400698 logs/LIB_NAME/VERSION/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400699
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400700 -log1-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400701 Log path for 1st version of a library.
702 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400703 logs/LIB_NAME/V1/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400704
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400705 -log2-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400706 Log path for 2nd version of a library.
707 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400708 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400709
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400710 -logging-mode MODE
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400711 Change logging mode.
712 Modes:
713 w - overwrite old logs (default)
714 a - append old logs
715 n - do not write any logs
716
717 -list-affected
718 Generate file with the list of incompatible
719 symbols beside the HTML compatibility report.
720 Use 'c++filt \@file' command from GNU binutils
721 to unmangle C++ symbols in the generated file.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400722 Default names:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400723 abi_affected.txt
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400724 src_affected.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400725
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400726 -component NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400727 The component name in the title and summary of the HTML report.
728 Default:
729 library
730
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400731 -l-full|-lib-full NAME
732 Change library name in the report title to NAME. By default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400733 will be displayed a name specified by -l option.
734
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400735 -b|-browse PROGRAM
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400736 Open report(s) in the browser (firefox, opera, etc.).
737
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400738 -open
739 Open report(s) in the default browser.
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400740
741 -extra-info DIR
742 Dump extra info to DIR.
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400743
744 -extra-dump
745 Create extended ABI dump containing all symbols
746 from the translation unit.
747
748 -force
749 Try to use this option if the tool doesn't work.
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400750
751 -tolerance LEVEL
752 Apply a set of heuristics to successfully compile input
753 header files. You can enable several tolerance levels by
754 joining them into one string (e.g. 13, 124, etc.).
755 Levels:
756 1 - skip non-Linux headers (e.g. win32_*.h, etc.)
757 2 - skip internal headers (e.g. *_p.h, impl/*.h, etc.)
758 3 - skip headers that iclude non-Linux headers
759 4 - skip headers included by others
760
761 -tolerant
762 Enable highest tolerance level [1234].
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400763
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400764REPORT:
765 Compatibility report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400766 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400767
768 Log will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400769 logs/LIB_NAME/V1/log.txt
770 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400771
772EXIT CODES:
773 0 - Compatible. The tool has run without any errors.
774 non-zero - Incompatible or the tool has run with errors.
775
776REPORT BUGS TO:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400777 Andrey Ponomarenko <aponomarenko\@rosalab.ru>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400778
779MORE INFORMATION:
780 ".$HomePage{"Wiki"}."
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400781 ".$HomePage{"Dev1"}."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400782}
783
784my $DescriptorTemplate = "
785<?xml version=\"1.0\" encoding=\"utf-8\"?>
786<descriptor>
787
788/* Primary sections */
789
790<version>
791 /* Version of the library */
792</version>
793
794<headers>
795 /* The list of paths to header files and/or
796 directories with header files, one per line */
797</headers>
798
799<libs>
800 /* The list of paths to shared libraries (*.$LIB_EXT) and/or
801 directories with shared libraries, one per line */
802</libs>
803
804/* Optional sections */
805
806<include_paths>
807 /* The list of include paths that will be provided
808 to GCC to compile library headers, one per line.
809 NOTE: If you define this section then the tool
810 will not automatically generate include paths */
811</include_paths>
812
813<add_include_paths>
814 /* The list of include paths that will be added
815 to the automatically generated include paths, one per line */
816</add_include_paths>
817
818<skip_include_paths>
819 /* The list of include paths that will be removed from the
820 list of automatically generated include paths, one per line */
821</skip_include_paths>
822
823<gcc_options>
824 /* Additional GCC options, one per line */
825</gcc_options>
826
827<include_preamble>
828 /* The list of header files that will be
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +0400829 included before other headers, one per line */
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400830</include_preamble>
831
832<defines>
833 /* The list of defines that will be added at the
834 headers compiling stage, one per line:
835 #define A B
836 #define C D */
837</defines>
838
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +0400839<add_namespaces>
840 /* The list of namespaces that should be added to the alanysis
841 if the tool cannot find them automatically, one per line */
842</add_namespaces>
843
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400844<skip_types>
845 /* The list of data types, that
846 should not be checked, one per line */
847</skip_types>
848
849<skip_symbols>
850 /* The list of functions (mangled/symbol names in C++),
851 that should not be checked, one per line */
852</skip_symbols>
853
854<skip_namespaces>
855 /* The list of C++ namespaces, that
856 should not be checked, one per line */
857</skip_namespaces>
858
859<skip_constants>
860 /* The list of constants that should
861 not be checked, one name per line */
862</skip_constants>
863
864<skip_headers>
865 /* The list of header files and/or directories
866 with header files that should not be checked, one per line */
867</skip_headers>
868
869<skip_libs>
870 /* The list of shared libraries and/or directories
871 with shared libraries that should not be checked, one per line */
872</skip_libs>
873
874<skip_including>
875 /* The list of header files, that cannot be included
876 directly (or non-self compiled ones), one per line */
877</skip_including>
878
879<search_headers>
880 /* List of directories to be searched
881 for header files to automatically
882 generate include paths, one per line. */
883</search_headers>
884
885<search_libs>
886 /* List of directories to be searched
887 for shared librariess to resolve
888 dependencies, one per line */
889</search_libs>
890
891<tools>
892 /* List of directories with tools used
893 for analysis (GCC toolchain), one per line */
894</tools>
895
896<cross_prefix>
897 /* GCC toolchain prefix.
898 Examples:
899 arm-linux-gnueabi
900 arm-none-symbianelf */
901</cross_prefix>
902
903</descriptor>";
904
905my %Operator_Indication = (
906 "not" => "~",
907 "assign" => "=",
908 "andassign" => "&=",
909 "orassign" => "|=",
910 "xorassign" => "^=",
911 "or" => "|",
912 "xor" => "^",
913 "addr" => "&",
914 "and" => "&",
915 "lnot" => "!",
916 "eq" => "==",
917 "ne" => "!=",
918 "lt" => "<",
919 "lshift" => "<<",
920 "lshiftassign" => "<<=",
921 "rshiftassign" => ">>=",
922 "call" => "()",
923 "mod" => "%",
924 "modassign" => "%=",
925 "subs" => "[]",
926 "land" => "&&",
927 "lor" => "||",
928 "rshift" => ">>",
929 "ref" => "->",
930 "le" => "<=",
931 "deref" => "*",
932 "mult" => "*",
933 "preinc" => "++",
934 "delete" => " delete",
935 "vecnew" => " new[]",
936 "vecdelete" => " delete[]",
937 "predec" => "--",
938 "postinc" => "++",
939 "postdec" => "--",
940 "plusassign" => "+=",
941 "plus" => "+",
942 "minus" => "-",
943 "minusassign" => "-=",
944 "gt" => ">",
945 "ge" => ">=",
946 "new" => " new",
947 "multassign" => "*=",
948 "divassign" => "/=",
949 "div" => "/",
950 "neg" => "-",
951 "pos" => "+",
952 "memref" => "->*",
953 "compound" => "," );
954
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400955my %UnknownOperator;
956
957my %NodeType= (
958 "array_type" => "Array",
959 "binfo" => "Other",
960 "boolean_type" => "Intrinsic",
961 "complex_type" => "Intrinsic",
962 "const_decl" => "Other",
963 "enumeral_type" => "Enum",
964 "field_decl" => "Other",
965 "function_decl" => "Other",
966 "function_type" => "FunctionType",
967 "identifier_node" => "Other",
968 "integer_cst" => "Other",
969 "integer_type" => "Intrinsic",
970 "method_type" => "MethodType",
971 "namespace_decl" => "Other",
972 "parm_decl" => "Other",
973 "pointer_type" => "Pointer",
974 "real_cst" => "Other",
975 "real_type" => "Intrinsic",
976 "record_type" => "Struct",
977 "reference_type" => "Ref",
978 "string_cst" => "Other",
979 "template_decl" => "Other",
980 "template_type_parm" => "Other",
981 "tree_list" => "Other",
982 "tree_vec" => "Other",
983 "type_decl" => "Other",
984 "union_type" => "Union",
985 "var_decl" => "Other",
986 "void_type" => "Intrinsic",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400987 "nop_expr" => "Other", #
988 "addr_expr" => "Other", #
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400989 "offset_type" => "Other" );
990
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400991my %CppKeywords_C = map {$_=>1} (
992 # C++ 2003 keywords
993 "public",
994 "protected",
995 "private",
996 "default",
997 "template",
998 "new",
999 #"asm",
1000 "dynamic_cast",
1001 "auto",
1002 "try",
1003 "namespace",
1004 "typename",
1005 "using",
1006 "reinterpret_cast",
1007 "friend",
1008 "class",
1009 "virtual",
1010 "const_cast",
1011 "mutable",
1012 "static_cast",
1013 "export",
1014 # C++0x keywords
1015 "noexcept",
1016 "nullptr",
1017 "constexpr",
1018 "static_assert",
1019 "explicit",
1020 # cannot be used as a macro name
1021 # as it is an operator in C++
1022 "and",
1023 #"and_eq",
1024 "not",
1025 #"not_eq",
1026 "or"
1027 #"or_eq",
1028 #"bitand",
1029 #"bitor",
1030 #"xor",
1031 #"xor_eq",
1032 #"compl"
1033);
1034
1035my %CppKeywords_F = map {$_=>1} (
1036 "delete",
1037 "catch",
1038 "alignof",
1039 "thread_local",
1040 "decltype",
1041 "typeid"
1042);
1043
1044my %CppKeywords_O = map {$_=>1} (
1045 "bool",
1046 "register",
1047 "inline",
1048 "operator"
1049);
1050
1051my %CppKeywords_A = map {$_=>1} (
1052 "this",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001053 "throw",
1054 "template"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001055);
1056
1057foreach (keys(%CppKeywords_C),
1058keys(%CppKeywords_F),
1059keys(%CppKeywords_O)) {
1060 $CppKeywords_A{$_}=1;
1061}
1062
1063# Header file extensions as described by gcc
1064my $HEADER_EXT = "h|hh|hp|hxx|hpp|h\\+\\+";
1065
1066my %IntrinsicMangling = (
1067 "void" => "v",
1068 "bool" => "b",
1069 "wchar_t" => "w",
1070 "char" => "c",
1071 "signed char" => "a",
1072 "unsigned char" => "h",
1073 "short" => "s",
1074 "unsigned short" => "t",
1075 "int" => "i",
1076 "unsigned int" => "j",
1077 "long" => "l",
1078 "unsigned long" => "m",
1079 "long long" => "x",
1080 "__int64" => "x",
1081 "unsigned long long" => "y",
1082 "__int128" => "n",
1083 "unsigned __int128" => "o",
1084 "float" => "f",
1085 "double" => "d",
1086 "long double" => "e",
1087 "__float80" => "e",
1088 "__float128" => "g",
1089 "..." => "z"
1090);
1091
1092my %StdcxxMangling = (
1093 "3std"=>"St",
1094 "3std9allocator"=>"Sa",
1095 "3std12basic_string"=>"Sb",
1096 "3std12basic_stringIcE"=>"Ss",
1097 "3std13basic_istreamIcE"=>"Si",
1098 "3std13basic_ostreamIcE"=>"So",
1099 "3std14basic_iostreamIcE"=>"Sd"
1100);
1101
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04001102my $DEFAULT_STD_PARMS = "std::(allocator|less|char_traits|regex_traits|istreambuf_iterator|ostreambuf_iterator)";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001103
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001104my %ConstantSuffix = (
1105 "unsigned int"=>"u",
1106 "long"=>"l",
1107 "unsigned long"=>"ul",
1108 "long long"=>"ll",
1109 "unsigned long long"=>"ull"
1110);
1111
1112my %ConstantSuffixR =
1113reverse(%ConstantSuffix);
1114
1115my %OperatorMangling = (
1116 "~" => "co",
1117 "=" => "aS",
1118 "|" => "or",
1119 "^" => "eo",
1120 "&" => "an",#ad (addr)
1121 "==" => "eq",
1122 "!" => "nt",
1123 "!=" => "ne",
1124 "<" => "lt",
1125 "<=" => "le",
1126 "<<" => "ls",
1127 "<<=" => "lS",
1128 ">" => "gt",
1129 ">=" => "ge",
1130 ">>" => "rs",
1131 ">>=" => "rS",
1132 "()" => "cl",
1133 "%" => "rm",
1134 "[]" => "ix",
1135 "&&" => "aa",
1136 "||" => "oo",
1137 "*" => "ml",#de (deref)
1138 "++" => "pp",#
1139 "--" => "mm",#
1140 "new" => "nw",
1141 "delete" => "dl",
1142 "new[]" => "na",
1143 "delete[]" => "da",
1144 "+=" => "pL",
1145 "+" => "pl",#ps (pos)
1146 "-" => "mi",#ng (neg)
1147 "-=" => "mI",
1148 "*=" => "mL",
1149 "/=" => "dV",
1150 "&=" => "aN",
1151 "|=" => "oR",
1152 "%=" => "rM",
1153 "^=" => "eO",
1154 "/" => "dv",
1155 "->*" => "pm",
1156 "->" => "pt",#rf (ref)
1157 "," => "cm",
1158 "?" => "qu",
1159 "." => "dt",
1160 "sizeof"=> "sz"#st
1161);
1162
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001163my %Intrinsic_Keywords = map {$_=>1} (
1164 "true",
1165 "false",
1166 "_Bool",
1167 "_Complex",
1168 "const",
1169 "int",
1170 "long",
1171 "void",
1172 "short",
1173 "float",
1174 "volatile",
1175 "restrict",
1176 "unsigned",
1177 "signed",
1178 "char",
1179 "double",
1180 "class",
1181 "struct",
1182 "union",
1183 "enum"
1184);
1185
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001186my %GlibcHeader = map {$_=>1} (
1187 "aliases.h",
1188 "argp.h",
1189 "argz.h",
1190 "assert.h",
1191 "cpio.h",
1192 "ctype.h",
1193 "dirent.h",
1194 "envz.h",
1195 "errno.h",
1196 "error.h",
1197 "execinfo.h",
1198 "fcntl.h",
1199 "fstab.h",
1200 "ftw.h",
1201 "glob.h",
1202 "grp.h",
1203 "iconv.h",
1204 "ifaddrs.h",
1205 "inttypes.h",
1206 "langinfo.h",
1207 "limits.h",
1208 "link.h",
1209 "locale.h",
1210 "malloc.h",
1211 "math.h",
1212 "mntent.h",
1213 "monetary.h",
1214 "nl_types.h",
1215 "obstack.h",
1216 "printf.h",
1217 "pwd.h",
1218 "regex.h",
1219 "sched.h",
1220 "search.h",
1221 "setjmp.h",
1222 "shadow.h",
1223 "signal.h",
1224 "spawn.h",
1225 "stdarg.h",
1226 "stdint.h",
1227 "stdio.h",
1228 "stdlib.h",
1229 "string.h",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001230 "strings.h",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001231 "tar.h",
1232 "termios.h",
1233 "time.h",
1234 "ulimit.h",
1235 "unistd.h",
1236 "utime.h",
1237 "wchar.h",
1238 "wctype.h",
1239 "wordexp.h" );
1240
1241my %GlibcDir = map {$_=>1} (
1242 "arpa",
1243 "bits",
1244 "gnu",
1245 "netinet",
1246 "net",
1247 "nfs",
1248 "rpc",
1249 "sys",
1250 "linux" );
1251
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001252my %WinHeaders = map {$_=>1} (
1253 "dos.h",
1254 "process.h",
1255 "winsock.h",
1256 "config-win.h",
1257 "mem.h",
1258 "windows.h",
1259 "winsock2.h",
1260 "crtdbg.h",
1261 "ws2tcpip.h"
1262);
1263
1264my %ObsoleteHeaders = map {$_=>1} (
1265 "iostream.h",
1266 "fstream.h"
1267);
1268
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001269my %AlienHeaders = map {$_=>1} (
1270 # Solaris
1271 "thread.h",
1272 "sys/atomic.h",
1273 # HPUX
1274 "sys/stream.h",
1275 # Symbian
1276 "AknDoc.h",
1277 # Atari ST
1278 "ext.h",
1279 "tos.h",
1280 # MS-DOS
1281 "alloc.h",
1282 # Sparc
1283 "sys/atomic.h"
1284);
1285
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001286my %ConfHeaders = map {$_=>1} (
1287 "atomic",
1288 "conf.h",
1289 "config.h",
1290 "configure.h",
1291 "build.h",
1292 "setup.h"
1293);
1294
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001295my %LocalIncludes = map {$_=>1} (
1296 "/usr/local/include",
1297 "/usr/local" );
1298
1299my %OS_AddPath=(
1300# These paths are needed if the tool cannot detect them automatically
1301 "macos"=>{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001302 "include"=>[
1303 "/Library",
1304 "/Developer/usr/include"
1305 ],
1306 "lib"=>[
1307 "/Library",
1308 "/Developer/usr/lib"
1309 ],
1310 "bin"=>[
1311 "/Developer/usr/bin"
1312 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001313 },
1314 "beos"=>{
1315 # Haiku has GCC 2.95.3 by default
1316 # try to find GCC>=3.0 in /boot/develop/abi
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001317 "include"=>[
1318 "/boot/common",
1319 "/boot/develop"
1320 ],
1321 "lib"=>[
1322 "/boot/common/lib",
1323 "/boot/system/lib",
1324 "/boot/apps"
1325 ],
1326 "bin"=>[
1327 "/boot/common/bin",
1328 "/boot/system/bin",
1329 "/boot/develop/abi"
1330 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001331 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001332);
1333
1334my %Slash_Type=(
1335 "default"=>"/",
1336 "windows"=>"\\"
1337);
1338
1339my $SLASH = $Slash_Type{$OSgroup}?$Slash_Type{$OSgroup}:$Slash_Type{"default"};
1340
1341# Global Variables
1342my %COMMON_LANGUAGE=(
1343 1 => "C",
1344 2 => "C" );
1345
1346my $MAX_COMMAND_LINE_ARGUMENTS = 4096;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001347my $MAX_CPPFILT_FILE_SIZE = 50000;
1348my $CPPFILT_SUPPORT_FILE;
1349
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001350my (%WORD_SIZE, %CPU_ARCH, %GCC_VERSION);
1351
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001352my $STDCXX_TESTING = 0;
1353my $GLIBC_TESTING = 0;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001354my $CPP_HEADERS = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001355
1356my $CheckHeadersOnly = $CheckHeadersOnly_Opt;
1357my $CheckObjectsOnly = $CheckObjectsOnly_Opt;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001358
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001359my $TargetComponent;
1360
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001361my $CheckUndefined = 0;
1362
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001363# Set Target Component Name
1364if($TargetComponent_Opt) {
1365 $TargetComponent = lc($TargetComponent_Opt);
1366}
1367else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001368{ # default: library
1369 # other components: header, system, ...
1370 $TargetComponent = "library";
1371}
1372
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001373my $TOP_REF = "<a style='font-size:11px;' href='#Top'>to the top</a>";
1374
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001375my $SystemRoot;
1376
1377my $MAIN_CPP_DIR;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001378my %RESULT;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001379my %LOG_PATH;
1380my %DEBUG_PATH;
1381my %Cache;
1382my %LibInfo;
1383my $COMPILE_ERRORS = 0;
1384my %CompilerOptions;
1385my %CheckedDyLib;
1386my $TargetLibraryShortName = parse_libname($TargetLibraryName, "shortest", $OSgroup);
1387
1388# Constants (#defines)
1389my %Constants;
1390my %SkipConstants;
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04001391my %EnumConstants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001392
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001393# Extra Info
1394my %SymbolHeader;
1395my %KnownLibs;
1396
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001397# Types
1398my %TypeInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001399my %TemplateInstance;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04001400my %TemplateDecl;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001401my %SkipTypes = (
1402 "1"=>{},
1403 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001404my %CheckedTypes;
1405my %TName_Tid;
1406my %EnumMembName_Id;
1407my %NestedNameSpaces = (
1408 "1"=>{},
1409 "2"=>{} );
1410my %UsedType;
1411my %VirtualTable;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001412my %VirtualTable_Model;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001413my %ClassVTable;
1414my %ClassVTable_Content;
1415my %VTableClass;
1416my %AllocableClass;
1417my %ClassMethods;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001418my %ClassNames;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001419my %Class_SubClasses;
1420my %OverriddenMethods;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04001421my %TypedefToAnon;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001422my $MAX_ID = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001423
1424# Typedefs
1425my %Typedef_BaseName;
1426my %Typedef_Tr;
1427my %Typedef_Eq;
1428my %StdCxxTypedef;
1429my %MissedTypedef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001430my %MissedBase;
1431my %MissedBase_R;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001432my %TypeTypedef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001433
1434# Symbols
1435my %SymbolInfo;
1436my %tr_name;
1437my %mangled_name_gcc;
1438my %mangled_name;
1439my %SkipSymbols = (
1440 "1"=>{},
1441 "2"=>{} );
1442my %SkipNameSpaces = (
1443 "1"=>{},
1444 "2"=>{} );
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001445my %AddNameSpaces = (
1446 "1"=>{},
1447 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001448my %SymbolsList;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001449my %SkipSymbolsList;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001450my %SymbolsList_App;
1451my %CheckedSymbols;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001452my %Symbol_Library = (
1453 "1"=>{},
1454 "2"=>{} );
1455my %Library_Symbol = (
1456 "1"=>{},
1457 "2"=>{} );
1458my %DepSymbol_Library = (
1459 "1"=>{},
1460 "2"=>{} );
1461my %DepLibrary_Symbol = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001462 "1"=>{},
1463 "2"=>{} );
1464my %MangledNames;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001465my %Func_ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001466my %AddIntParams;
1467my %Interface_Impl;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001468my %GlobalDataObject;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001469my %WeakSymbols;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001470my %Library_Needed= (
1471 "1"=>{},
1472 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001473
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001474# Extra Info
1475my %UndefinedSymbols;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001476my %PreprocessedHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001477
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001478# Headers
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001479my %Include_Preamble = (
1480 "1"=>[],
1481 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001482my %Registered_Headers;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001483my %Registered_Sources;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001484my %HeaderName_Paths;
1485my %Header_Dependency;
1486my %Include_Neighbors;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001487my %Include_Paths = (
1488 "1"=>[],
1489 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001490my %INC_PATH_AUTODETECT = (
1491 "1"=>1,
1492 "2"=>1 );
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001493my %Add_Include_Paths = (
1494 "1"=>[],
1495 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001496my %Skip_Include_Paths;
1497my %RegisteredDirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001498my %Header_ErrorRedirect;
1499my %Header_Includes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001500my %Header_Includes_R;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001501my %Header_ShouldNotBeUsed;
1502my %RecursiveIncludes;
1503my %Header_Include_Prefix;
1504my %SkipHeaders;
1505my %SkipHeadersList=(
1506 "1"=>{},
1507 "2"=>{} );
1508my %SkipLibs;
1509my %Include_Order;
1510my %TUnit_NameSpaces;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001511my %TUnit_Classes;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001512my %TUnit_Funcs;
1513my %TUnit_Vars;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001514
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001515my %CppMode = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001516 "1"=>0,
1517 "2"=>0 );
1518my %AutoPreambleMode = (
1519 "1"=>0,
1520 "2"=>0 );
1521my %MinGWMode = (
1522 "1"=>0,
1523 "2"=>0 );
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001524my %Cpp0xMode = (
1525 "1"=>0,
1526 "2"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001527
1528# Shared Objects
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001529my %RegisteredObjects;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001530my %RegisteredObjects_Short;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001531my %RegisteredSONAMEs;
1532my %RegisteredObject_Dirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001533
1534# System Objects
1535my %SystemObjects;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001536my @DefaultLibPaths;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001537my %DyLib_DefaultPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001538
1539# System Headers
1540my %SystemHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001541my @DefaultCppPaths;
1542my @DefaultGccPaths;
1543my @DefaultIncPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001544my %DefaultCppHeader;
1545my %DefaultGccHeader;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001546my @UsersIncPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001547
1548# Merging
1549my %CompleteSignature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001550my $Version;
1551my %AddedInt;
1552my %RemovedInt;
1553my %AddedInt_Virt;
1554my %RemovedInt_Virt;
1555my %VirtualReplacement;
1556my %ChangedTypedef;
1557my %CompatRules;
1558my %IncompleteRules;
1559my %UnknownRules;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001560my %VTableChanged_M;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001561my %ExtendedSymbols;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001562my %ReturnedClass;
1563my %ParamClass;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001564my %SourceAlternative;
1565my %SourceAlternative_B;
1566my %SourceReplacement;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001567
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001568# Calling Conventions
1569my %UseConv_Real = (
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001570 1=>{ "R"=>0, "P"=>0 },
1571 2=>{ "R"=>0, "P"=>0 }
1572);
1573
1574# ABI Dump
1575my %UsedDump;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001576
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001577# OS Compliance
1578my %TargetLibs;
1579my %TargetHeaders;
1580
1581# OS Specifics
1582my $OStarget = $OSgroup;
1583my %TargetTools;
1584
1585# Compliance Report
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001586my %Type_MaxSeverity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001587
1588# Recursion locks
1589my @RecurLib;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001590my @RecurTypes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001591my @RecurTypes_Diff;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001592my @RecurInclude;
1593my @RecurConstant;
1594
1595# System
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001596my %SystemPaths = (
1597 "include"=>[],
1598 "lib"=>[],
1599 "bin"=>[]
1600);
1601my @DefaultBinPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001602my $GCC_PATH;
1603
1604# Symbols versioning
1605my %SymVer = (
1606 "1"=>{},
1607 "2"=>{} );
1608
1609# Problem descriptions
1610my %CompatProblems;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001611my %CompatProblems_Constants;
1612my %CompatProblems_Impl;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001613my %TotalAffected;
1614
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001615# Reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001616my $ContentID = 1;
1617my $ContentSpanStart = "<span class=\"section\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1618my $ContentSpanStart_Affected = "<span class=\"section_affected\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1619my $ContentSpanStart_Info = "<span class=\"section_info\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1620my $ContentSpanEnd = "</span>\n";
1621my $ContentDivStart = "<div id=\"CONTENT_ID\" style=\"display:none;\">\n";
1622my $ContentDivEnd = "</div>\n";
1623my $Content_Counter = 0;
1624
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001625# Modes
1626my $JoinReport = 1;
1627my $DoubleReport = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001628
1629sub get_Modules()
1630{
1631 my $TOOL_DIR = get_dirname($0);
1632 if(not $TOOL_DIR)
1633 { # patch for MS Windows
1634 $TOOL_DIR = ".";
1635 }
1636 my @SEARCH_DIRS = (
1637 # tool's directory
1638 abs_path($TOOL_DIR),
1639 # relative path to modules
1640 abs_path($TOOL_DIR)."/../share/abi-compliance-checker",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001641 # install path
1642 'MODULES_INSTALL_PATH'
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001643 );
1644 foreach my $DIR (@SEARCH_DIRS)
1645 {
1646 if(not is_abs($DIR))
1647 { # relative path
1648 $DIR = abs_path($TOOL_DIR)."/".$DIR;
1649 }
1650 if(-d $DIR."/modules") {
1651 return $DIR."/modules";
1652 }
1653 }
1654 exitStatus("Module_Error", "can't find modules");
1655}
1656
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001657my %LoadedModules = ();
1658
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001659sub loadModule($)
1660{
1661 my $Name = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001662 if(defined $LoadedModules{$Name}) {
1663 return;
1664 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001665 my $Path = $MODULES_DIR."/Internals/$Name.pm";
1666 if(not -f $Path) {
1667 exitStatus("Module_Error", "can't access \'$Path\'");
1668 }
1669 require $Path;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001670 $LoadedModules{$Name} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001671}
1672
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001673sub readModule($$)
1674{
1675 my ($Module, $Name) = @_;
1676 my $Path = $MODULES_DIR."/Internals/$Module/".$Name;
1677 if(not -f $Path) {
1678 exitStatus("Module_Error", "can't access \'$Path\'");
1679 }
1680 return readFile($Path);
1681}
1682
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04001683sub showPos($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001684{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001685 my $Number = $_[0];
1686 if(not $Number) {
1687 $Number = 1;
1688 }
1689 else {
1690 $Number = int($Number)+1;
1691 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001692 if($Number>3) {
1693 return $Number."th";
1694 }
1695 elsif($Number==1) {
1696 return "1st";
1697 }
1698 elsif($Number==2) {
1699 return "2nd";
1700 }
1701 elsif($Number==3) {
1702 return "3rd";
1703 }
1704 else {
1705 return $Number;
1706 }
1707}
1708
1709sub search_Tools($)
1710{
1711 my $Name = $_[0];
1712 return "" if(not $Name);
1713 if(my @Paths = keys(%TargetTools))
1714 {
1715 foreach my $Path (@Paths)
1716 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001717 if(-f join_P($Path, $Name)) {
1718 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001719 }
1720 if($CrossPrefix)
1721 { # user-defined prefix (arm-none-symbianelf, ...)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001722 my $Candidate = join_P($Path, $CrossPrefix."-".$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001723 if(-f $Candidate) {
1724 return $Candidate;
1725 }
1726 }
1727 }
1728 }
1729 else {
1730 return "";
1731 }
1732}
1733
1734sub synch_Cmd($)
1735{
1736 my $Name = $_[0];
1737 if(not $GCC_PATH)
1738 { # GCC was not found yet
1739 return "";
1740 }
1741 my $Candidate = $GCC_PATH;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001742 if($Candidate=~s/\bgcc(|\.\w+)\Z/$Name$1/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001743 return $Candidate;
1744 }
1745 return "";
1746}
1747
1748sub get_CmdPath($)
1749{
1750 my $Name = $_[0];
1751 return "" if(not $Name);
1752 if(defined $Cache{"get_CmdPath"}{$Name}) {
1753 return $Cache{"get_CmdPath"}{$Name};
1754 }
1755 my %BinUtils = map {$_=>1} (
1756 "c++filt",
1757 "objdump",
1758 "readelf"
1759 );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001760 if($BinUtils{$Name} and $GCC_PATH)
1761 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001762 if(my $Dir = get_dirname($GCC_PATH)) {
1763 $TargetTools{$Dir}=1;
1764 }
1765 }
1766 my $Path = search_Tools($Name);
1767 if(not $Path and $OSgroup eq "windows") {
1768 $Path = search_Tools($Name.".exe");
1769 }
1770 if(not $Path and $BinUtils{$Name})
1771 {
1772 if($CrossPrefix)
1773 { # user-defined prefix
1774 $Path = search_Cmd($CrossPrefix."-".$Name);
1775 }
1776 }
1777 if(not $Path and $BinUtils{$Name})
1778 {
1779 if(my $Candidate = synch_Cmd($Name))
1780 { # synch with GCC
1781 if($Candidate=~/[\/\\]/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001782 { # command path
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001783 if(-f $Candidate) {
1784 $Path = $Candidate;
1785 }
1786 }
1787 elsif($Candidate = search_Cmd($Candidate))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001788 { # command name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001789 $Path = $Candidate;
1790 }
1791 }
1792 }
1793 if(not $Path) {
1794 $Path = search_Cmd($Name);
1795 }
1796 if(not $Path and $OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001797 { # search for *.exe file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001798 $Path=search_Cmd($Name.".exe");
1799 }
1800 if($Path=~/\s/) {
1801 $Path = "\"".$Path."\"";
1802 }
1803 return ($Cache{"get_CmdPath"}{$Name}=$Path);
1804}
1805
1806sub search_Cmd($)
1807{
1808 my $Name = $_[0];
1809 return "" if(not $Name);
1810 if(defined $Cache{"search_Cmd"}{$Name}) {
1811 return $Cache{"search_Cmd"}{$Name};
1812 }
1813 if(my $DefaultPath = get_CmdPath_Default($Name)) {
1814 return ($Cache{"search_Cmd"}{$Name} = $DefaultPath);
1815 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001816 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001817 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001818 my $CmdPath = join_P($Path,$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001819 if(-f $CmdPath)
1820 {
1821 if($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001822 next if(not check_gcc($CmdPath, "3"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001823 }
1824 return ($Cache{"search_Cmd"}{$Name} = $CmdPath);
1825 }
1826 }
1827 return ($Cache{"search_Cmd"}{$Name} = "");
1828}
1829
1830sub get_CmdPath_Default($)
1831{ # search in PATH
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001832 return "" if(not $_[0]);
1833 if(defined $Cache{"get_CmdPath_Default"}{$_[0]}) {
1834 return $Cache{"get_CmdPath_Default"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001835 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001836 return ($Cache{"get_CmdPath_Default"}{$_[0]} = get_CmdPath_Default_I($_[0]));
1837}
1838
1839sub get_CmdPath_Default_I($)
1840{ # search in PATH
1841 my $Name = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001842 if($Name=~/find/)
1843 { # special case: search for "find" utility
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001844 if(`find \"$TMP_DIR\" -maxdepth 0 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001845 return "find";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001846 }
1847 }
1848 elsif($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001849 return check_gcc($Name, "3");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001850 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001851 if(checkCmd($Name)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001852 return $Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001853 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001854 if($OSgroup eq "windows")
1855 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001856 if(`$Name /? 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001857 return $Name;
1858 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001859 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001860 foreach my $Path (@DefaultBinPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001861 {
1862 if(-f $Path."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001863 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001864 }
1865 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001866 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001867}
1868
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001869sub classifyPath($)
1870{
1871 my $Path = $_[0];
1872 if($Path=~/[\*\[]/)
1873 { # wildcard
1874 $Path=~s/\*/.*/g;
1875 $Path=~s/\\/\\\\/g;
1876 return ($Path, "Pattern");
1877 }
1878 elsif($Path=~/[\/\\]/)
1879 { # directory or relative path
1880 return (path_format($Path, $OSgroup), "Path");
1881 }
1882 else {
1883 return ($Path, "Name");
1884 }
1885}
1886
1887sub readDescriptor($$)
1888{
1889 my ($LibVersion, $Content) = @_;
1890 return if(not $LibVersion);
1891 my $DName = $DumpAPI?"descriptor":"descriptor \"d$LibVersion\"";
1892 if(not $Content) {
1893 exitStatus("Error", "$DName is empty");
1894 }
1895 if($Content!~/\</) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04001896 exitStatus("Error", "incorrect descriptor (see -d1 option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001897 }
1898 $Content=~s/\/\*(.|\n)+?\*\///g;
1899 $Content=~s/<\!--(.|\n)+?-->//g;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001900
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001901 $Descriptor{$LibVersion}{"Version"} = parseTag(\$Content, "version");
1902 if($TargetVersion{$LibVersion}) {
1903 $Descriptor{$LibVersion}{"Version"} = $TargetVersion{$LibVersion};
1904 }
1905 if(not $Descriptor{$LibVersion}{"Version"}) {
1906 exitStatus("Error", "version in the $DName is not specified (<version> section)");
1907 }
1908 if($Content=~/{RELPATH}/)
1909 {
1910 if(my $RelDir = $RelativeDirectory{$LibVersion}) {
1911 $Content =~ s/{RELPATH}/$RelDir/g;
1912 }
1913 else
1914 {
1915 my $NeedRelpath = $DumpAPI?"-relpath":"-relpath$LibVersion";
1916 exitStatus("Error", "you have not specified $NeedRelpath option, but the $DName contains {RELPATH} macro");
1917 }
1918 }
1919
1920 if(not $CheckObjectsOnly_Opt)
1921 {
1922 my $DHeaders = parseTag(\$Content, "headers");
1923 if(not $DHeaders) {
1924 exitStatus("Error", "header files in the $DName are not specified (<headers> section)");
1925 }
1926 elsif(lc($DHeaders) ne "none")
1927 { # append the descriptor headers list
1928 if($Descriptor{$LibVersion}{"Headers"})
1929 { # multiple descriptors
1930 $Descriptor{$LibVersion}{"Headers"} .= "\n".$DHeaders;
1931 }
1932 else {
1933 $Descriptor{$LibVersion}{"Headers"} = $DHeaders;
1934 }
1935 foreach my $Path (split(/\s*\n\s*/, $DHeaders))
1936 {
1937 if(not -e $Path) {
1938 exitStatus("Access_Error", "can't access \'$Path\'");
1939 }
1940 }
1941 }
1942 }
1943 if(not $CheckHeadersOnly_Opt)
1944 {
1945 my $DObjects = parseTag(\$Content, "libs");
1946 if(not $DObjects) {
1947 exitStatus("Error", "$SLIB_TYPE libraries in the $DName are not specified (<libs> section)");
1948 }
1949 elsif(lc($DObjects) ne "none")
1950 { # append the descriptor libraries list
1951 if($Descriptor{$LibVersion}{"Libs"})
1952 { # multiple descriptors
1953 $Descriptor{$LibVersion}{"Libs"} .= "\n".$DObjects;
1954 }
1955 else {
1956 $Descriptor{$LibVersion}{"Libs"} .= $DObjects;
1957 }
1958 foreach my $Path (split(/\s*\n\s*/, $DObjects))
1959 {
1960 if(not -e $Path) {
1961 exitStatus("Access_Error", "can't access \'$Path\'");
1962 }
1963 }
1964 }
1965 }
1966 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers")))
1967 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001968 if(not -d $Path) {
1969 exitStatus("Access_Error", "can't access directory \'$Path\'");
1970 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001971 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001972 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001973 push_U($SystemPaths{"include"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001974 }
1975 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs")))
1976 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001977 if(not -d $Path) {
1978 exitStatus("Access_Error", "can't access directory \'$Path\'");
1979 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001980 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001981 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001982 push_U($SystemPaths{"lib"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001983 }
1984 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools")))
1985 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001986 if(not -d $Path) {
1987 exitStatus("Access_Error", "can't access directory \'$Path\'");
1988 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001989 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001990 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001991 push_U($SystemPaths{"bin"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001992 $TargetTools{$Path}=1;
1993 }
1994 if(my $Prefix = parseTag(\$Content, "cross_prefix")) {
1995 $CrossPrefix = $Prefix;
1996 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001997 $Descriptor{$LibVersion}{"IncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"IncludePaths"}); # perl 5.8 doesn't support //=
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001998 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "include_paths")))
1999 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002000 if(not -d $Path) {
2001 exitStatus("Access_Error", "can't access directory \'$Path\'");
2002 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002003 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002004 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002005 push(@{$Descriptor{$LibVersion}{"IncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002006 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002007 $Descriptor{$LibVersion}{"AddIncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"AddIncludePaths"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002008 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "add_include_paths")))
2009 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002010 if(not -d $Path) {
2011 exitStatus("Access_Error", "can't access directory \'$Path\'");
2012 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002013 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002014 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002015 push(@{$Descriptor{$LibVersion}{"AddIncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002016 }
2017 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_include_paths")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002018 { # skip some auto-generated include paths
2019 if(not is_abs($Path))
2020 {
2021 if(my $P = abs_path($Path)) {
2022 $Path = $P;
2023 }
2024 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002025 $Skip_Include_Paths{$LibVersion}{path_format($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002026 }
2027 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_including")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002028 { # skip direct including of some headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002029 my ($CPath, $Type) = classifyPath($Path);
2030 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002031 }
2032 $Descriptor{$LibVersion}{"GccOptions"} = parseTag(\$Content, "gcc_options");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002033 foreach my $Option (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"GccOptions"}))
2034 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002035 if($Option!~/\A\-(Wl|l|L)/)
2036 { # skip linker options
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002037 $CompilerOptions{$LibVersion} .= " ".$Option;
2038 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002039 }
2040 $Descriptor{$LibVersion}{"SkipHeaders"} = parseTag(\$Content, "skip_headers");
2041 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipHeaders"}))
2042 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002043 $SkipHeadersList{$LibVersion}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002044 my ($CPath, $Type) = classifyPath($Path);
2045 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002046 }
2047 $Descriptor{$LibVersion}{"SkipLibs"} = parseTag(\$Content, "skip_libs");
2048 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipLibs"}))
2049 {
2050 my ($CPath, $Type) = classifyPath($Path);
2051 $SkipLibs{$LibVersion}{$Type}{$CPath} = 1;
2052 }
2053 if(my $DDefines = parseTag(\$Content, "defines"))
2054 {
2055 if($Descriptor{$LibVersion}{"Defines"})
2056 { # multiple descriptors
2057 $Descriptor{$LibVersion}{"Defines"} .= "\n".$DDefines;
2058 }
2059 else {
2060 $Descriptor{$LibVersion}{"Defines"} = $DDefines;
2061 }
2062 }
2063 foreach my $Order (split(/\s*\n\s*/, parseTag(\$Content, "include_order")))
2064 {
2065 if($Order=~/\A(.+):(.+)\Z/) {
2066 $Include_Order{$LibVersion}{$1} = $2;
2067 }
2068 }
2069 foreach my $Type_Name (split(/\s*\n\s*/, parseTag(\$Content, "opaque_types")),
2070 split(/\s*\n\s*/, parseTag(\$Content, "skip_types")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002071 { # opaque_types renamed to skip_types (1.23.4)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002072 $SkipTypes{$LibVersion}{$Type_Name} = 1;
2073 }
2074 foreach my $Symbol (split(/\s*\n\s*/, parseTag(\$Content, "skip_interfaces")),
2075 split(/\s*\n\s*/, parseTag(\$Content, "skip_symbols")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002076 { # skip_interfaces renamed to skip_symbols (1.22.1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002077 $SkipSymbols{$LibVersion}{$Symbol} = 1;
2078 }
2079 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "skip_namespaces"))) {
2080 $SkipNameSpaces{$LibVersion}{$NameSpace} = 1;
2081 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04002082 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "add_namespaces"))) {
2083 $AddNameSpaces{$LibVersion}{$NameSpace} = 1;
2084 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002085 foreach my $Constant (split(/\s*\n\s*/, parseTag(\$Content, "skip_constants"))) {
2086 $SkipConstants{$LibVersion}{$Constant} = 1;
2087 }
2088 if(my $DIncPreamble = parseTag(\$Content, "include_preamble"))
2089 {
2090 if($Descriptor{$LibVersion}{"IncludePreamble"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002091 { # multiple descriptors
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002092 $Descriptor{$LibVersion}{"IncludePreamble"} .= "\n".$DIncPreamble;
2093 }
2094 else {
2095 $Descriptor{$LibVersion}{"IncludePreamble"} = $DIncPreamble;
2096 }
2097 }
2098}
2099
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002100sub parseTag(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002101{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002102 my $CodeRef = shift(@_);
2103 my $Tag = shift(@_);
2104 if(not $Tag or not $CodeRef) {
2105 return undef;
2106 }
2107 my $Sp = 0;
2108 if(@_) {
2109 $Sp = shift(@_);
2110 }
2111 my $Start = index(${$CodeRef}, "<$Tag>");
2112 if($Start!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002113 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002114 my $End = index(${$CodeRef}, "</$Tag>");
2115 if($End!=-1)
2116 {
2117 my $TS = length($Tag)+3;
2118 my $Content = substr(${$CodeRef}, $Start, $End-$Start+$TS, "");
2119 substr($Content, 0, $TS-1, ""); # cut start tag
2120 substr($Content, -$TS, $TS, ""); # cut end tag
2121 if(not $Sp)
2122 {
2123 $Content=~s/\A\s+//g;
2124 $Content=~s/\s+\Z//g;
2125 }
2126 if(substr($Content, 0, 1) ne "<") {
2127 $Content = xmlSpecChars_R($Content);
2128 }
2129 return $Content;
2130 }
2131 }
2132 return undef;
2133}
2134
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002135sub getInfo($)
2136{
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002137 my $DumpPath = $_[0];
2138 return if(not $DumpPath or not -f $DumpPath);
2139
2140 readTUDump($DumpPath);
2141
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002142 # processing info
2143 setTemplateParams_All();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002144
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002145 if($ExtraDump) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002146 setAnonTypedef_All();
2147 }
2148
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002149 getTypeInfo_All();
2150 simplifyNames();
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002151 simplifyConstants();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002152 getVarInfo_All();
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002153 getSymbolInfo_All();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002154
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002155
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002156 # clean memory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002157 %LibInfo = ();
2158 %TemplateInstance = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002159 %MangledNames = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002160 %TemplateDecl = ();
2161 %StdCxxTypedef = ();
2162 %MissedTypedef = ();
2163 %Typedef_Tr = ();
2164 %Typedef_Eq = ();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002165 %TypedefToAnon = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002166
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002167 # clean cache
2168 delete($Cache{"getTypeAttr"});
2169 delete($Cache{"getTypeDeclId"});
2170
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002171 if($ExtraDump)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002172 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002173 foreach (keys(%{$TypeInfo{$Version}}))
2174 {
2175 if($TypeInfo{$Version}{$_}{"Artificial"}) {
2176 delete($TypeInfo{$Version}{$_});
2177 }
2178 }
2179 }
2180 else
2181 { # remove unused types
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002182 if($BinaryOnly and not $ExtendedCheck)
2183 { # --binary
2184 removeUnused($Version, "All");
2185 }
2186 else {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002187 removeUnused($Version, "Extended");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002188 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002189 }
2190
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002191 if($Debug) {
2192 # debugMangling($Version);
2193 }
2194}
2195
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002196sub readTUDump($)
2197{
2198 my $DumpPath = $_[0];
2199
2200 open(TU_DUMP, $DumpPath);
2201 local $/ = undef;
2202 my $Content = <TU_DUMP>;
2203 close(TU_DUMP);
2204
2205 unlink($DumpPath);
2206
2207 $Content=~s/\n[ ]+/ /g;
2208 my @Lines = split("\n", $Content);
2209
2210 # clean memory
2211 undef $Content;
2212
2213 $MAX_ID = $#Lines+1;
2214
2215 foreach (0 .. $#Lines)
2216 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002217 if($Lines[$_]=~/\A\@(\d+)[ ]+([a-z_]+)[ ]+(.+)\Z/i)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002218 { # get a number and attributes of a node
2219 next if(not $NodeType{$2});
2220 $LibInfo{$Version}{"info_type"}{$1}=$2;
2221 $LibInfo{$Version}{"info"}{$1}=$3;
2222 }
2223
2224 # clean memory
2225 delete($Lines[$_]);
2226 }
2227
2228 # clean memory
2229 undef @Lines;
2230}
2231
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002232sub simplifyConstants()
2233{
2234 foreach my $Constant (keys(%{$Constants{$Version}}))
2235 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002236 if(defined $Constants{$Version}{$Constant}{"Header"})
2237 {
2238 my $Value = $Constants{$Version}{$Constant}{"Value"};
2239 if(defined $EnumConstants{$Version}{$Value}) {
2240 $Constants{$Version}{$Constant}{"Value"} = $EnumConstants{$Version}{$Value}{"Value"};
2241 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002242 }
2243 }
2244}
2245
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002246sub simplifyNames()
2247{
2248 foreach my $Base (keys(%{$Typedef_Tr{$Version}}))
2249 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002250 if($Typedef_Eq{$Version}{$Base}) {
2251 next;
2252 }
2253 my @Translations = sort keys(%{$Typedef_Tr{$Version}{$Base}});
2254 if($#Translations==0)
2255 {
2256 if(length($Translations[0])<=length($Base)) {
2257 $Typedef_Eq{$Version}{$Base} = $Translations[0];
2258 }
2259 }
2260 else
2261 { # select most appropriate
2262 foreach my $Tr (@Translations)
2263 {
2264 if($Base=~/\A\Q$Tr\E/)
2265 {
2266 $Typedef_Eq{$Version}{$Base} = $Tr;
2267 last;
2268 }
2269 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002270 }
2271 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002272 foreach my $TypeId (keys(%{$TypeInfo{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002273 {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002274 my $TypeName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002275 if(not $TypeName) {
2276 next;
2277 }
2278 next if(index($TypeName,"<")==-1);# template instances only
2279 if($TypeName=~/>(::\w+)+\Z/)
2280 { # skip unused types
2281 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002282 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002283 foreach my $Base (sort {length($b)<=>length($a)}
2284 sort {$b cmp $a} keys(%{$Typedef_Eq{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002285 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002286 next if(not $Base);
2287 next if(index($TypeName,$Base)==-1);
2288 next if(length($TypeName) - length($Base) <= 3);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002289 if(my $Typedef = $Typedef_Eq{$Version}{$Base})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002290 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002291 $TypeName=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g;
2292 $TypeName=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g;
2293 if(defined $TypeInfo{$Version}{$TypeId}{"TParam"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002294 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002295 foreach my $TPos (keys(%{$TypeInfo{$Version}{$TypeId}{"TParam"}}))
2296 {
2297 if(my $TPName = $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"})
2298 {
2299 $TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g;
2300 $TPName=~s/\A\Q$Base\E(\w|\Z)/$Typedef $1/g;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002301 $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName, "T");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002302 }
2303 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002304 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002305 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002306 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002307 $TypeName = formatName($TypeName, "T");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002308 $TypeInfo{$Version}{$TypeId}{"Name"} = $TypeName;
2309 $TName_Tid{$Version}{$TypeName} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002310 }
2311}
2312
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002313sub setAnonTypedef_All()
2314{
2315 foreach my $InfoId (keys(%{$LibInfo{$Version}{"info"}}))
2316 {
2317 if($LibInfo{$Version}{"info_type"}{$InfoId} eq "type_decl")
2318 {
2319 if(isAnon(getNameByInfo($InfoId))) {
2320 $TypedefToAnon{getTypeId($InfoId)} = 1;
2321 }
2322 }
2323 }
2324}
2325
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002326sub setTemplateParams_All()
2327{
2328 foreach (keys(%{$LibInfo{$Version}{"info"}}))
2329 {
2330 if($LibInfo{$Version}{"info_type"}{$_} eq "template_decl") {
2331 setTemplateParams($_);
2332 }
2333 }
2334}
2335
2336sub setTemplateParams($)
2337{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002338 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002339 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002340 if($Info=~/(inst|spcs)[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002341 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002342 my $TmplInst_Id = $2;
2343 setTemplateInstParams($TmplInst_Id);
2344 while($TmplInst_Id = getNextElem($TmplInst_Id)) {
2345 setTemplateInstParams($TmplInst_Id);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002346 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002347 }
2348 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002349 if(my $TypeId = getTreeAttr_Type($_[0]))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002350 {
2351 if(my $IType = $LibInfo{$Version}{"info_type"}{$TypeId})
2352 {
2353 if($IType eq "record_type") {
2354 $TemplateDecl{$Version}{$TypeId}=1;
2355 }
2356 }
2357 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002358}
2359
2360sub setTemplateInstParams($)
2361{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002362 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002363 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002364 my ($Params_InfoId, $ElemId) = ();
2365 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
2366 $Params_InfoId = $1;
2367 }
2368 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
2369 $ElemId = $1;
2370 }
2371 if($Params_InfoId and $ElemId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002372 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002373 my $Params_Info = $LibInfo{$Version}{"info"}{$Params_InfoId};
2374 while($Params_Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
2375 {
2376 my ($PPos, $PTypeId) = ($1, $2);
2377 if(my $PType = $LibInfo{$Version}{"info_type"}{$PTypeId})
2378 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002379 if($PType eq "template_type_parm")
2380 {
2381 $TemplateDecl{$Version}{$ElemId}=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002382 return;
2383 }
2384 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002385 if($LibInfo{$Version}{"info_type"}{$ElemId} eq "function_decl")
2386 { # functions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002387 $TemplateInstance{$Version}{"Func"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002388 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002389 else
2390 { # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002391 $TemplateInstance{$Version}{"Type"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002392 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002393 }
2394 }
2395 }
2396}
2397
2398sub getTypeDeclId($)
2399{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002400 if($_[0])
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002401 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002402 if(defined $Cache{"getTypeDeclId"}{$Version}{$_[0]}) {
2403 return $Cache{"getTypeDeclId"}{$Version}{$_[0]};
2404 }
2405 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2406 {
2407 if($Info=~/name[ ]*:[ ]*@(\d+)/) {
2408 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = $1);
2409 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002410 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002411 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002412 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002413}
2414
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002415sub getTypeInfo_All()
2416{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002417 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002418 { # support for GCC < 4.5
2419 # missed typedefs: QStyle::State is typedef to QFlags<QStyle::StateFlag>
2420 # but QStyleOption.state is of type QFlags<QStyle::StateFlag> in the TU dump
2421 # FIXME: check GCC versions
2422 addMissedTypes_Pre();
2423 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002424
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002425 foreach (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002426 { # forward order only
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002427 my $IType = $LibInfo{$Version}{"info_type"}{$_};
2428 if($IType=~/_type\Z/ and $IType ne "function_type"
2429 and $IType ne "method_type") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002430 getTypeInfo("$_");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002431 }
2432 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002433
2434 # add "..." type
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002435 $TypeInfo{$Version}{"-1"} = {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002436 "Name" => "...",
2437 "Type" => "Intrinsic",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002438 "Tid" => "-1"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002439 };
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002440 $TName_Tid{$Version}{"..."} = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002441
2442 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002443 { # support for GCC < 4.5
2444 addMissedTypes_Post();
2445 }
2446}
2447
2448sub addMissedTypes_Pre()
2449{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002450 my %MissedTypes = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002451 foreach my $MissedTDid (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
2452 { # detecting missed typedefs
2453 if($LibInfo{$Version}{"info_type"}{$MissedTDid} eq "type_decl")
2454 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002455 my $TypeId = getTreeAttr_Type($MissedTDid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002456 next if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002457 my $TypeType = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002458 if($TypeType eq "Unknown")
2459 { # template_type_parm
2460 next;
2461 }
2462 my $TypeDeclId = getTypeDeclId($TypeId);
2463 next if($TypeDeclId eq $MissedTDid);#or not $TypeDeclId
2464 my $TypedefName = getNameByInfo($MissedTDid);
2465 next if(not $TypedefName);
2466 next if($TypedefName eq "__float80");
2467 next if(isAnon($TypedefName));
2468 if(not $TypeDeclId
2469 or getNameByInfo($TypeDeclId) ne $TypedefName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002470 $MissedTypes{$Version}{$TypeId}{$MissedTDid} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002471 }
2472 }
2473 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002474 my %AddTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002475 foreach my $Tid (keys(%{$MissedTypes{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002476 { # add missed typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002477 my @Missed = keys(%{$MissedTypes{$Version}{$Tid}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002478 if(not @Missed or $#Missed>=1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002479 next;
2480 }
2481 my $MissedTDid = $Missed[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002482 my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002483 if(not $TypedefName) {
2484 next;
2485 }
2486 $MAX_ID++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002487 my %MissedInfo = ( # typedef info
2488 "Name" => $TypedefName,
2489 "NameSpace" => $TypedefNS,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002490 "BaseType" => $Tid,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002491 "Type" => "Typedef",
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002492 "Tid" => "$MAX_ID" );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002493 my ($H, $L) = getLocation($MissedTDid);
2494 $MissedInfo{"Header"} = $H;
2495 $MissedInfo{"Line"} = $L;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002496 if($TypedefName=~/\*|\&|\s/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002497 { # other types
2498 next;
2499 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002500 if($TypedefName=~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002501 { # QFlags<Qt::DropAction>::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002502 next;
2503 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002504 if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002505 { # double-check for the name of typedef
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002506 my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002507 next if(not $TName);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002508 if(length($TypedefName)>=length($TName))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002509 { # too long typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002510 next;
2511 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002512 if($TName=~/\A\Q$TypedefName\E</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002513 next;
2514 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002515 if($TypedefName=~/\A\Q$TName\E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002516 { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002517 next;
2518 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002519 if(get_depth($TypedefName)==0 and get_depth($TName)!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002520 { # std::_Vector_base and std::vector::_Base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002521 next;
2522 }
2523 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002524
2525 $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo;
2526
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002527 # register typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002528 $MissedTypedef{$Version}{$Tid}{"Tid"} = $MissedInfo{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002529 $MissedTypedef{$Version}{$Tid}{"TDid"} = $MissedTDid;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002530 $TName_Tid{$Version}{$TypedefName} = $MissedInfo{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002531 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002532
2533 # add missed & remove other
2534 $TypeInfo{$Version} = \%AddTypes;
2535 delete($Cache{"getTypeAttr"}{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002536}
2537
2538sub addMissedTypes_Post()
2539{
2540 foreach my $BaseId (keys(%{$MissedTypedef{$Version}}))
2541 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002542 if(my $Tid = $MissedTypedef{$Version}{$BaseId}{"Tid"})
2543 {
2544 $TypeInfo{$Version}{$Tid}{"Size"} = $TypeInfo{$Version}{$BaseId}{"Size"};
2545 if(my $TName = $TypeInfo{$Version}{$Tid}{"Name"}) {
2546 $Typedef_BaseName{$Version}{$TName} = $TypeInfo{$Version}{$BaseId}{"Name"};
2547 }
2548 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002549 }
2550}
2551
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002552sub getTypeInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002553{
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002554 my $TypeId = $_[0];
2555 %{$TypeInfo{$Version}{$TypeId}} = getTypeAttr($TypeId);
2556 my $TName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002557 if(not $TName) {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002558 delete($TypeInfo{$Version}{$TypeId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002559 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002560}
2561
2562sub getArraySize($$)
2563{
2564 my ($TypeId, $BaseName) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002565 if(my $Size = getSize($TypeId))
2566 {
2567 my $Elems = $Size/$BYTE_SIZE;
2568 while($BaseName=~s/\s*\[(\d+)\]//) {
2569 $Elems/=$1;
2570 }
2571 if(my $BasicId = $TName_Tid{$Version}{$BaseName})
2572 {
2573 if(my $BasicSize = $TypeInfo{$Version}{$BasicId}{"Size"}) {
2574 $Elems/=$BasicSize;
2575 }
2576 }
2577 return $Elems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002578 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002579 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002580}
2581
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002582sub getTParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002583{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002584 my ($TypeId, $Kind) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002585 my @TmplParams = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002586 my @Positions = sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$Kind}{$TypeId}});
2587 foreach my $Pos (@Positions)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002588 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002589 my $Param_TypeId = $TemplateInstance{$Version}{$Kind}{$TypeId}{$Pos};
2590 my $NodeType = $LibInfo{$Version}{"info_type"}{$Param_TypeId};
2591 if(not $NodeType)
2592 { # typename_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002593 return ();
2594 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002595 if($NodeType eq "tree_vec")
2596 {
2597 if($Pos!=$#Positions)
2598 { # select last vector of parameters ( ns<P1>::type<P2> )
2599 next;
2600 }
2601 }
2602 my @Params = get_TemplateParam($Pos, $Param_TypeId);
2603 foreach my $P (@Params)
2604 {
2605 if($P eq "") {
2606 return ();
2607 }
2608 elsif($P ne "\@skip\@") {
2609 @TmplParams = (@TmplParams, $P);
2610 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002611 }
2612 }
2613 return @TmplParams;
2614}
2615
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002616sub getTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002617{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002618 my $TypeId = $_[0];
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002619 my %TypeAttr = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002620 if(defined $TypeInfo{$Version}{$TypeId}
2621 and $TypeInfo{$Version}{$TypeId}{"Name"})
2622 { # already created
2623 return %{$TypeInfo{$Version}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002624 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002625 elsif($Cache{"getTypeAttr"}{$Version}{$TypeId})
2626 { # incomplete type
2627 return ();
2628 }
2629 $Cache{"getTypeAttr"}{$Version}{$TypeId} = 1;
2630
2631 my $TypeDeclId = getTypeDeclId($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002632 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002633
2634 if(not $MissedBase{$Version}{$TypeId} and isTypedef($TypeId))
2635 {
2636 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
2637 {
2638 if($Info=~/qual[ ]*:/)
2639 {
2640 if(my $NID = ++$MAX_ID)
2641 {
2642 $MissedBase{$Version}{$TypeId}="$NID";
2643 $MissedBase_R{$Version}{$NID}=$TypeId;
2644 $LibInfo{$Version}{"info"}{$NID} = $LibInfo{$Version}{"info"}{$TypeId};
2645 $LibInfo{$Version}{"info_type"}{$NID} = $LibInfo{$Version}{"info_type"}{$TypeId};
2646 }
2647 }
2648 }
2649 $TypeAttr{"Type"} = "Typedef";
2650 }
2651 else {
2652 $TypeAttr{"Type"} = getTypeType($TypeId);
2653 }
2654
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002655 if($TypeAttr{"Type"} eq "Unknown") {
2656 return ();
2657 }
2658 elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/)
2659 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002660 %TypeAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"});
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002661 if(my $TName = $TypeAttr{"Name"})
2662 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002663 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002664 $TName_Tid{$Version}{$TName} = $TypeId;
2665 return %TypeAttr;
2666 }
2667 else {
2668 return ();
2669 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002670 }
2671 elsif($TypeAttr{"Type"} eq "Array")
2672 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002673 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2674 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002675 return ();
2676 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002677 if(my $Algn = getAlgn($TypeId)) {
2678 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2679 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002680 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002681 if(my %BTAttr = getTypeAttr($BTid))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002682 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002683 if(not $BTAttr{"Name"}) {
2684 return ();
2685 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002686 if(my $NElems = getArraySize($TypeId, $BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002687 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002688 if(my $Size = getSize($TypeId)) {
2689 $TypeAttr{"Size"} = $Size/$BYTE_SIZE;
2690 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002691 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002692 $TypeAttr{"Name"} = $1."[$NElems]".$2;
2693 }
2694 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002695 $TypeAttr{"Name"} = $BTAttr{"Name"}."[$NElems]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002696 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002697 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002698 else
2699 {
2700 $TypeAttr{"Size"} = $WORD_SIZE{$Version}; # pointer
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002701 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002702 $TypeAttr{"Name"} = $1."[]".$2;
2703 }
2704 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002705 $TypeAttr{"Name"} = $BTAttr{"Name"}."[]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002706 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002707 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002708 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002709 if($BTAttr{"Header"}) {
2710 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002711 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002712 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002713 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2714 return %TypeAttr;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002715 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002716 return ();
2717 }
2718 elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
2719 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002720 %TypeAttr = getTrivialTypeAttr($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002721 if($TypeAttr{"Name"})
2722 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002723 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2724 if($TypeAttr{"Name"} ne "int" or getTypeDeclId($TypeAttr{"Tid"}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002725 { # NOTE: register only one int: with built-in decl
2726 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2727 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2728 }
2729 }
2730 return %TypeAttr;
2731 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002732 else {
2733 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002734 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002735 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002736 else
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002737 { # derived types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002738 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2739 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002740 return ();
2741 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002742 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002743 if(defined $MissedTypedef{$Version}{$BTid})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002744 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002745 if(my $MissedTDid = $MissedTypedef{$Version}{$BTid}{"TDid"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002746 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002747 if($MissedTDid ne $TypeDeclId) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002748 $TypeAttr{"BaseType"} = $MissedTypedef{$Version}{$BTid}{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002749 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002750 }
2751 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002752 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002753 if(not $BTAttr{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002754 { # templates
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002755 return ();
2756 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002757 if($BTAttr{"Type"} eq "Typedef")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002758 { # relinking typedefs
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002759 my %BaseBase = get_Type($BTAttr{"BaseType"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002760 if($BTAttr{"Name"} eq $BaseBase{"Name"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002761 $TypeAttr{"BaseType"} = $BaseBase{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002762 }
2763 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002764 if($BTSpec)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002765 {
2766 if($TypeAttr{"Type"} eq "Pointer"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002767 and $BTAttr{"Name"}=~/\([\*]+\)/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002768 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002769 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002770 $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g;
2771 }
2772 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002773 $TypeAttr{"Name"} = $BTAttr{"Name"}." ".$BTSpec;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002774 }
2775 }
2776 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002777 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002778 }
2779 if($TypeAttr{"Type"} eq "Typedef")
2780 {
2781 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002782
2783 if(index($TypeAttr{"Name"}, "tmp_add_type")==0) {
2784 return ();
2785 }
2786
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002787 if(isAnon($TypeAttr{"Name"}))
2788 { # anon typedef to anon type: ._N
2789 return ();
2790 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002791
2792 if($LibInfo{$Version}{"info"}{$TypeDeclId}=~/ artificial /i)
2793 { # artificial typedef of "struct X" to "X"
2794 $TypeAttr{"Artificial"} = 1;
2795 }
2796
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002797 if(my $NS = getNameSpace($TypeDeclId))
2798 {
2799 my $TypeName = $TypeAttr{"Name"};
2800 if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/)
2801 { # "some_type" is the typedef to "struct some_type" in C++
2802 if($3) {
2803 $TypeAttr{"Name"} = $3."::".$TypeName;
2804 }
2805 }
2806 else
2807 {
2808 $TypeAttr{"NameSpace"} = $NS;
2809 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002810
2811 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/
2812 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/)
2813 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002814 if($BTAttr{"NameSpace"}
2815 and $BTAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr{"Name"}=~/</)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002816 { # types like "std::fpos<__mbstate_t>" are
2817 # not covered by typedefs in the TU dump
2818 # so trying to add such typedefs manually
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002819 $StdCxxTypedef{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2820 if(length($TypeAttr{"Name"})<=length($BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002821 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002822 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002823 { # skip "other" in "std" and "type" in "boost"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002824 $Typedef_Eq{$Version}{$BTAttr{"Name"}} = $TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002825 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002826 }
2827 }
2828 }
2829 }
2830 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002831 if($TypeAttr{"Name"} ne $BTAttr{"Name"} and not $TypeAttr{"Artificial"}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002832 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr{"Name"}!~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002833 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002834 if(not defined $Typedef_BaseName{$Version}{$TypeAttr{"Name"}})
2835 { # typedef int*const TYPEDEF; // first
2836 # int foo(TYPEDEF p); // const is optimized out
2837 $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BTAttr{"Name"};
2838 if($BTAttr{"Name"}=~/</)
2839 {
2840 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) {
2841 $Typedef_Tr{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2842 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002843 }
2844 }
2845 }
2846 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId);
2847 }
2848 if(not $TypeAttr{"Size"})
2849 {
2850 if($TypeAttr{"Type"} eq "Pointer") {
2851 $TypeAttr{"Size"} = $WORD_SIZE{$Version};
2852 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002853 elsif($BTAttr{"Size"}) {
2854 $TypeAttr{"Size"} = $BTAttr{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002855 }
2856 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002857 if(my $Algn = getAlgn($TypeId)) {
2858 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2859 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002860 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002861 if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) {
2862 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002863 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002864 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002865 if($TypeAttr{"Name"} ne $BTAttr{"Name"})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002866 { # typedef to "class Class"
2867 # should not be registered in TName_Tid
2868 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2869 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2870 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002871 }
2872 return %TypeAttr;
2873 }
2874}
2875
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002876sub getTreeVec($)
2877{
2878 my %Vector = ();
2879 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2880 {
2881 while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
2882 { # string length is N-1 because of the null terminator
2883 $Vector{$1} = $2;
2884 }
2885 }
2886 return \%Vector;
2887}
2888
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002889sub get_TemplateParam($$)
2890{
2891 my ($Pos, $Type_Id) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002892 return () if(not $Type_Id);
2893 my $NodeType = $LibInfo{$Version}{"info_type"}{$Type_Id};
2894 return () if(not $NodeType);
2895 if($NodeType eq "integer_cst")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002896 { # int (1), unsigned (2u), char ('c' as 99), ...
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002897 my $CstTid = getTreeAttr_Type($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002898 my %CstType = getTypeAttr($CstTid); # without recursion
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002899 my $Num = getNodeIntCst($Type_Id);
2900 if(my $CstSuffix = $ConstantSuffix{$CstType{"Name"}}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002901 return ($Num.$CstSuffix);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002902 }
2903 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002904 return ("(".$CstType{"Name"}.")".$Num);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002905 }
2906 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002907 elsif($NodeType eq "string_cst") {
2908 return (getNodeStrCst($Type_Id));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002909 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002910 elsif($NodeType eq "tree_vec")
2911 {
2912 my $Vector = getTreeVec($Type_Id);
2913 my @Params = ();
2914 foreach my $P1 (sort {int($a)<=>int($b)} keys(%{$Vector}))
2915 {
2916 foreach my $P2 (get_TemplateParam($Pos, $Vector->{$P1})) {
2917 push(@Params, $P2);
2918 }
2919 }
2920 return @Params;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002921 }
2922 else
2923 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002924 my %ParamAttr = getTypeAttr($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002925 my $PName = $ParamAttr{"Name"};
2926 if(not $PName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002927 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002928 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002929 if($PName=~/\>/)
2930 {
2931 if(my $Cover = cover_stdcxx_typedef($PName)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002932 $PName = $Cover;
2933 }
2934 }
2935 if($Pos>=1 and
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04002936 $PName=~/\A$DEFAULT_STD_PARMS\</)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002937 { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
2938 # template<typename _Key, typename _Compare = std::less<_Key>
2939 # template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
2940 # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> >
2941 # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
2942 # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> >
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002943 return ("\@skip\@");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002944 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002945 return ($PName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002946 }
2947}
2948
2949sub cover_stdcxx_typedef($)
2950{
2951 my $TypeName = $_[0];
2952 if(my @Covers = sort {length($a)<=>length($b)}
2953 sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
2954 { # take the shortest typedef
2955 # FIXME: there may be more than
2956 # one typedefs to the same type
2957 return $Covers[0];
2958 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002959 my $Covered = $TypeName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002960 while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){};
2961 if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
2962 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002963 if(my $Cover = $Covers[0])
2964 {
2965 $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
2966 $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
2967 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002968 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002969 return formatName($Covered, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002970}
2971
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002972sub getNodeIntCst($)
2973{
2974 my $CstId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002975 my $CstTypeId = getTreeAttr_Type($CstId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002976 if($EnumMembName_Id{$Version}{$CstId}) {
2977 return $EnumMembName_Id{$Version}{$CstId};
2978 }
2979 elsif((my $Value = getTreeValue($CstId)) ne "")
2980 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002981 if($Value eq "0")
2982 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002983 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002984 return "false";
2985 }
2986 else {
2987 return "0";
2988 }
2989 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002990 elsif($Value eq "1")
2991 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002992 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002993 return "true";
2994 }
2995 else {
2996 return "1";
2997 }
2998 }
2999 else {
3000 return $Value;
3001 }
3002 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003003 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003004}
3005
3006sub getNodeStrCst($)
3007{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003008 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3009 {
3010 if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003011 {
3012 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "string_cst")
3013 { # string length is N-1 because of the null terminator
3014 return substr($1, 0, $2-1);
3015 }
3016 else
3017 { # identifier_node
3018 return substr($1, 0, $2);
3019 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003020 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003021 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003022 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003023}
3024
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003025sub getMemPtrAttr($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003026{ # function, method and field pointers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003027 my ($PtrId, $TypeId, $Type) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003028 my $MemInfo = $LibInfo{$Version}{"info"}{$PtrId};
3029 if($Type eq "FieldPtr") {
3030 $MemInfo = $LibInfo{$Version}{"info"}{$TypeId};
3031 }
3032 my $MemInfo_Type = $LibInfo{$Version}{"info_type"}{$PtrId};
3033 my $MemPtrName = "";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003034 my %TypeAttr = ("Size"=>$WORD_SIZE{$Version}, "Type"=>$Type, "Tid"=>$TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003035 if($Type eq "MethodPtr")
3036 { # size of "method pointer" may be greater than WORD size
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003037 if(my $Size = getSize($TypeId))
3038 {
3039 $Size/=$BYTE_SIZE;
3040 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003041 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003042 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003043 if(my $Algn = getAlgn($TypeId)) {
3044 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3045 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003046 # Return
3047 if($Type eq "FieldPtr")
3048 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003049 my %ReturnAttr = getTypeAttr($PtrId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003050 if($ReturnAttr{"Name"}) {
3051 $MemPtrName .= $ReturnAttr{"Name"};
3052 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003053 $TypeAttr{"Return"} = $PtrId;
3054 }
3055 else
3056 {
3057 if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /)
3058 {
3059 my $ReturnTypeId = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003060 my %ReturnAttr = getTypeAttr($ReturnTypeId);
3061 if(not $ReturnAttr{"Name"})
3062 { # templates
3063 return ();
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003064 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003065 $MemPtrName .= $ReturnAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003066 $TypeAttr{"Return"} = $ReturnTypeId;
3067 }
3068 }
3069 # Class
3070 if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /)
3071 {
3072 $TypeAttr{"Class"} = $2;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003073 my %Class = getTypeAttr($TypeAttr{"Class"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003074 if($Class{"Name"}) {
3075 $MemPtrName .= " (".$Class{"Name"}."\:\:*)";
3076 }
3077 else {
3078 $MemPtrName .= " (*)";
3079 }
3080 }
3081 else {
3082 $MemPtrName .= " (*)";
3083 }
3084 # Parameters
3085 if($Type eq "FuncPtr"
3086 or $Type eq "MethodPtr")
3087 {
3088 my @ParamTypeName = ();
3089 if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /)
3090 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003091 my $PTypeInfoId = $1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003092 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003093 while($PTypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003094 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003095 my $PTypeInfo = $LibInfo{$Version}{"info"}{$PTypeInfoId};
3096 if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003097 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003098 my $PTypeId = $1;
3099 my %ParamAttr = getTypeAttr($PTypeId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003100 if(not $ParamAttr{"Name"})
3101 { # templates (template_type_parm), etc.
3102 return ();
3103 }
3104 if($ParamAttr{"Name"} eq "void") {
3105 last;
3106 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003107 if($Pos!=0 or $Type ne "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003108 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003109 $TypeAttr{"Param"}{$PPos++}{"type"} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003110 push(@ParamTypeName, $ParamAttr{"Name"});
3111 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003112 if($PTypeInfoId = getNextElem($PTypeInfoId)) {
3113 $Pos+=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003114 }
3115 else {
3116 last;
3117 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003118 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003119 else {
3120 last;
3121 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003122 }
3123 }
3124 $MemPtrName .= " (".join(", ", @ParamTypeName).")";
3125 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003126 $TypeAttr{"Name"} = formatName($MemPtrName, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003127 return %TypeAttr;
3128}
3129
3130sub getTreeTypeName($)
3131{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003132 my $TypeId = $_[0];
3133 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003134 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003135 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "integer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003136 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003137 if(my $Name = getNameByInfo($TypeId))
3138 { # bit_size_type
3139 return $Name;
3140 }
3141 elsif($Info=~/unsigned/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003142 return "unsigned int";
3143 }
3144 else {
3145 return "int";
3146 }
3147 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003148 elsif($Info=~/name[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003149 return getNameByInfo($1);
3150 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003151 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003152 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003153}
3154
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003155sub isFuncPtr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003156{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003157 my $Ptd = pointTo($_[0]);
3158 return 0 if(not $Ptd);
3159 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003160 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003161 if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) {
3162 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003163 }
3164 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003165 if(my $InfoT1 = $LibInfo{$Version}{"info_type"}{$_[0]}
3166 and my $InfoT2 = $LibInfo{$Version}{"info_type"}{$Ptd})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003167 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003168 if($InfoT1 eq "pointer_type"
3169 and $InfoT2 eq "function_type") {
3170 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003171 }
3172 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003173 return 0;
3174}
3175
3176sub isMethodPtr($)
3177{
3178 my $Ptd = pointTo($_[0]);
3179 return 0 if(not $Ptd);
3180 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3181 {
3182 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "record_type"
3183 and $LibInfo{$Version}{"info_type"}{$Ptd} eq "method_type"
3184 and $Info=~/ ptrmem /) {
3185 return 1;
3186 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003187 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003188 return 0;
3189}
3190
3191sub isFieldPtr($)
3192{
3193 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3194 {
3195 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "offset_type"
3196 and $Info=~/ ptrmem /) {
3197 return 1;
3198 }
3199 }
3200 return 0;
3201}
3202
3203sub pointTo($)
3204{
3205 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3206 {
3207 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) {
3208 return $1;
3209 }
3210 }
3211 return "";
3212}
3213
3214sub getTypeTypeByTypeId($)
3215{
3216 my $TypeId = $_[0];
3217 if(my $TType = $LibInfo{$Version}{"info_type"}{$TypeId})
3218 {
3219 my $NType = $NodeType{$TType};
3220 if($NType eq "Intrinsic") {
3221 return $NType;
3222 }
3223 elsif(isFuncPtr($TypeId)) {
3224 return "FuncPtr";
3225 }
3226 elsif(isMethodPtr($TypeId)) {
3227 return "MethodPtr";
3228 }
3229 elsif(isFieldPtr($TypeId)) {
3230 return "FieldPtr";
3231 }
3232 elsif($NType ne "Other") {
3233 return $NType;
3234 }
3235 }
3236 return "Unknown";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003237}
3238
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003239my %UnQual = (
3240 "r"=>"restrict",
3241 "v"=>"volatile",
3242 "c"=>"const",
3243 "cv"=>"const volatile"
3244);
3245
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003246sub getQual($)
3247{
3248 my $TypeId = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003249 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
3250 {
3251 my ($Qual, $To) = ();
3252 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) {
3253 $Qual = $UnQual{$1};
3254 }
3255 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) {
3256 $To = $1;
3257 }
3258 if($Qual and $To) {
3259 return ($Qual, $To);
3260 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003261 }
3262 return ();
3263}
3264
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003265sub getQualType($)
3266{
3267 if($_[0] eq "const volatile") {
3268 return "ConstVolatile";
3269 }
3270 return ucfirst($_[0]);
3271}
3272
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003273sub getTypeType($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003274{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003275 my $TypeId = $_[0];
3276 my $TypeDeclId = getTypeDeclId($TypeId);
3277 if(defined $MissedTypedef{$Version}{$TypeId})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003278 { # support for old GCC versions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003279 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq $TypeDeclId) {
3280 return "Typedef";
3281 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003282 }
3283 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3284 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003285 if(($Qual or $To) and $TypeDeclId
3286 and (getTypeId($TypeDeclId) ne $TypeId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003287 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003288 return getQualType($Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003289 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003290 elsif(not $MissedBase_R{$Version}{$TypeId}
3291 and isTypedef($TypeId)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003292 return "Typedef";
3293 }
3294 elsif($Qual)
3295 { # qualified types
3296 return getQualType($Qual);
3297 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003298
3299 if($Info=~/unql[ ]*:[ ]*\@(\d+)/)
3300 { # typedef struct { ... } name
3301 $TypeTypedef{$Version}{$TypeId} = $1;
3302 }
3303
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003304 my $TypeType = getTypeTypeByTypeId($TypeId);
3305 if($TypeType eq "Struct")
3306 {
3307 if($TypeDeclId
3308 and $LibInfo{$Version}{"info_type"}{$TypeDeclId} eq "template_decl") {
3309 return "Template";
3310 }
3311 }
3312 return $TypeType;
3313}
3314
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003315sub isTypedef($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003316{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003317 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3318 {
3319 my $TDid = getTypeDeclId($_[0]);
3320 if(getNameByInfo($TDid)
3321 and $Info=~/unql[ ]*:[ ]*\@(\d+) /
3322 and getTypeId($TDid) eq $_[0]) {
3323 return $1;
3324 }
3325 }
3326 return 0;
3327}
3328
3329sub selectBaseType($)
3330{
3331 my $TypeId = $_[0];
3332 if(defined $MissedTypedef{$Version}{$TypeId})
3333 { # add missed typedefs
3334 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) {
3335 return ($TypeId, "");
3336 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003337 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003338 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3339 my $InfoType = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003340
3341 my $MB_R = $MissedBase_R{$Version}{$TypeId};
3342 my $MB = $MissedBase{$Version}{$TypeId};
3343
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003344 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003345 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) /
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003346 and (getTypeId($1) ne $TypeId)
3347 and (not $MB_R or getTypeId($1) ne $MB_R))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003348 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003349 return (getTypeId($1), $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003350 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003351 elsif($MB)
3352 { # add base
3353 return ($MB, "");
3354 }
3355 elsif(not $MB_R and my $Bid = isTypedef($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003356 { # typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003357 return ($Bid, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003358 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003359 elsif($Qual or $To)
3360 { # qualified types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003361 return ($To, $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003362 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003363 elsif($InfoType eq "reference_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003364 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003365 if($Info=~/refd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003366 return ($1, "&");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003367 }
3368 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003369 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003370 }
3371 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003372 elsif($InfoType eq "array_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003373 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003374 if($Info=~/elts[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003375 return ($1, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003376 }
3377 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003378 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003379 }
3380 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003381 elsif($InfoType eq "pointer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003382 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003383 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003384 return ($1, "*");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003385 }
3386 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003387 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003388 }
3389 }
3390 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003391 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003392 }
3393}
3394
3395sub getSymbolInfo_All()
3396{
3397 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3398 { # reverse order
3399 if($LibInfo{$Version}{"info_type"}{$_} eq "function_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003400 getSymbolInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003401 }
3402 }
3403}
3404
3405sub getVarInfo_All()
3406{
3407 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3408 { # reverse order
3409 if($LibInfo{$Version}{"info_type"}{$_} eq "var_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003410 getVarInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003411 }
3412 }
3413}
3414
3415sub isBuiltIn($) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003416 return ($_[0] and $_[0]=~/\<built\-in\>|\<internal\>|\A\./);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003417}
3418
3419sub getVarInfo($)
3420{
3421 my $InfoId = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003422 if(my $NSid = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003423 {
3424 my $NSInfoType = $LibInfo{$Version}{"info_type"}{$NSid};
3425 if($NSInfoType and $NSInfoType eq "function_decl") {
3426 return;
3427 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003428 }
3429 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
3430 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
3431 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) {
3432 delete($SymbolInfo{$Version}{$InfoId});
3433 return;
3434 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003435 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId));
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003436 if(not $ShortName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003437 delete($SymbolInfo{$Version}{$InfoId});
3438 return;
3439 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003440 if($ShortName=~/\Atmp_add_class_\d+\Z/) {
3441 delete($SymbolInfo{$Version}{$InfoId});
3442 return;
3443 }
3444 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003445 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
3446 {
3447 if($OSgroup eq "windows")
3448 { # cut the offset
3449 $MnglName=~s/\@\d+\Z//g;
3450 }
3451 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
3452 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003453 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003454 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003455 { # validate mangled name
3456 delete($SymbolInfo{$Version}{$InfoId});
3457 return;
3458 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003459 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003460 and index($ShortName, "_Z")==0)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003461 { # _ZTS, etc.
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003462 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003463 }
3464 if(isPrivateData($SymbolInfo{$Version}{$InfoId}{"MnglName"}))
3465 { # non-public global data
3466 delete($SymbolInfo{$Version}{$InfoId});
3467 return;
3468 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003469 $SymbolInfo{$Version}{$InfoId}{"Data"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003470 if(my $Rid = getTypeId($InfoId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003471 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003472 if(not $TypeInfo{$Version}{$Rid}{"Name"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003473 { # typename_type
3474 delete($SymbolInfo{$Version}{$InfoId});
3475 return;
3476 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003477 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Rid;
3478 my $Val = getDataVal($InfoId, $Rid);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003479 if(defined $Val) {
3480 $SymbolInfo{$Version}{$InfoId}{"Value"} = $Val;
3481 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003482 }
3483 set_Class_And_Namespace($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003484 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3485 {
3486 if(not $TypeInfo{$Version}{$ClassId}{"Name"})
3487 { # templates
3488 delete($SymbolInfo{$Version}{$InfoId});
3489 return;
3490 }
3491 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003492 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
3493 { # extern "C"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003494 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003495 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003496 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003497 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003498 { # --lang=C option
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003499 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003500 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04003501 if(not $CheckHeadersOnly)
3502 {
3503 if(not $SymbolInfo{$Version}{$InfoId}{"Class"})
3504 {
3505 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
3506 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
3507 {
3508 if(link_symbol($ShortName, $Version, "-Deps"))
3509 { # "const" global data is mangled as _ZL... in the TU dump
3510 # but not mangled when compiling a C shared library
3511 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3512 }
3513 }
3514 }
3515 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003516 if($COMMON_LANGUAGE{$Version} eq "C++")
3517 {
3518 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3519 { # for some symbols (_ZTI) the short name is the mangled name
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003520 if(index($ShortName, "_Z")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003521 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3522 }
3523 }
3524 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3525 { # try to mangle symbol (link with libraries)
3526 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = linkSymbol($InfoId);
3527 }
3528 if($OStarget eq "windows")
3529 {
3530 if(my $Mangled = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
3531 { # link MS C++ symbols from library with GCC symbols from headers
3532 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
3533 }
3534 }
3535 }
3536 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) {
3537 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3538 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003539 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3540 {
3541 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
3542 { # non-target symbols
3543 delete($SymbolInfo{$Version}{$InfoId});
3544 return;
3545 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003546 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003547 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
3548 {
3549 if(defined $MissedTypedef{$Version}{$Rid})
3550 {
3551 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
3552 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
3553 }
3554 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003555 }
3556 setFuncAccess($InfoId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003557 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_ZTV")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003558 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
3559 }
3560 if($ShortName=~/\A(_Z|\?)/) {
3561 delete($SymbolInfo{$Version}{$InfoId}{"ShortName"});
3562 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003563
3564 if($ExtraDump) {
3565 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
3566 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003567}
3568
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003569sub isConstType($$)
3570{
3571 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003572 my %Base = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003573 while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003574 %Base = get_OneStep_BaseType($Base{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003575 }
3576 return ($Base{"Type"} eq "Const");
3577}
3578
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003579sub getTrivialName($$)
3580{
3581 my ($TypeInfoId, $TypeId) = @_;
3582 my %TypeAttr = ();
3583 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId);
3584 if(not $TypeAttr{"Name"}) {
3585 $TypeAttr{"Name"} = getTreeTypeName($TypeId);
3586 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003587 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003588 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003589 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003590 if(isAnon($TypeAttr{"Name"}))
3591 {
3592 my $NameSpaceId = $TypeId;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003593 while(my $NSId = getTreeAttr_Scpe(getTypeDeclId($NameSpaceId)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003594 { # searching for a first not anon scope
3595 if($NSId eq $NameSpaceId) {
3596 last;
3597 }
3598 else
3599 {
3600 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId));
3601 if(not $TypeAttr{"NameSpace"}
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003602 or not isAnon($TypeAttr{"NameSpace"})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003603 last;
3604 }
3605 }
3606 $NameSpaceId=$NSId;
3607 }
3608 }
3609 else
3610 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003611 if(my $NameSpaceId = getTreeAttr_Scpe($TypeInfoId))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003612 {
3613 if($NameSpaceId ne $TypeId) {
3614 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId);
3615 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003616 }
3617 }
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003618 if($TypeAttr{"NameSpace"} and not isAnon($TypeAttr{"Name"})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003619 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3620 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003621 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003622 if(isAnon($TypeAttr{"Name"}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003623 { # anon-struct-header.h-line
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003624 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003625 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003626 if($TypeAttr{"NameSpace"}) {
3627 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3628 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003629 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003630 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId}
3631 and getTypeDeclId($TypeId) eq $TypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003632 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003633 my @TParams = getTParams($TypeId, "Type");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003634 if(not @TParams)
3635 { # template declarations with abstract params
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003636 return ("", "");
3637 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003638 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003639 }
3640 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"});
3641}
3642
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003643sub getTrivialTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003644{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003645 my $TypeId = $_[0];
3646 my $TypeInfoId = getTypeDeclId($_[0]);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003647
3648 if($TemplateDecl{$Version}{$TypeId})
3649 { # template_decl
3650 return ();
3651 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003652 if(my $ScopeId = getTreeAttr_Scpe($TypeInfoId))
3653 {
3654 if($TemplateDecl{$Version}{$ScopeId})
3655 { # template_decl
3656 return ();
3657 }
3658 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003659
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003660 my %TypeAttr = ();
3661 if(getTypeTypeByTypeId($TypeId)!~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/) {
3662 return ();
3663 }
3664 setTypeAccess($TypeId, \%TypeAttr);
3665 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
3666 if(isBuiltIn($TypeAttr{"Header"}))
3667 {
3668 delete($TypeAttr{"Header"});
3669 delete($TypeAttr{"Line"});
3670 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003671 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003672 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId);
3673 if(not $TypeAttr{"Name"}) {
3674 return ();
3675 }
3676 if(not $TypeAttr{"NameSpace"}) {
3677 delete($TypeAttr{"NameSpace"});
3678 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003679 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003680 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003681 if(my @TParams = getTParams($TypeId, "Type"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003682 {
3683 foreach my $Pos (0 .. $#TParams) {
3684 $TypeAttr{"TParam"}{$Pos}{"name"}=$TParams[$Pos];
3685 }
3686 }
3687 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003688 if(my $Size = getSize($TypeId))
3689 {
3690 $Size = $Size/$BYTE_SIZE;
3691 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003692 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003693 else
3694 { # declaration only
3695 $TypeAttr{"Forward"} = 1;
3696 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003697
3698 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr);
3699
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003700 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003701 and ($StaticFields or detect_lang($TypeId)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003702 {
3703 $TypeAttr{"Type"} = "Class";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003704 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003705 }
3706 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003707 or $TypeAttr{"Type"} eq "Class")
3708 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003709 my $Skip = setBaseClasses($TypeId, \%TypeAttr);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003710 if($Skip) {
3711 return ();
3712 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003713 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003714 if(my $Algn = getAlgn($TypeId)) {
3715 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3716 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003717 setSpec($TypeId, \%TypeAttr);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003718
3719 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/)
3720 {
3721 if(not $TypedefToAnon{$TypeId}
3722 and not keys(%{$TemplateInstance{$Version}{"Type"}{$TypeId}}))
3723 {
3724 if(not isAnon($TypeAttr{"Name"})) {
3725 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"};
3726 }
3727 }
3728 }
3729
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003730 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003731 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}})
3732 {
3733 my @Entries = split(/\n/, $VTable);
3734 foreach (1 .. $#Entries)
3735 {
3736 my $Entry = $Entries[$_];
3737 if($Entry=~/\A(\d+)\s+(.+)\Z/) {
3738 $TypeAttr{"VTable"}{$1} = $2;
3739 }
3740 }
3741 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04003742
3743 if($TypeAttr{"Type"} eq "Enum")
3744 {
3745 if(not $TypeAttr{"NameSpace"})
3746 {
3747 foreach my $Pos (keys(%{$TypeAttr{"Memb"}}))
3748 {
3749 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04003750 my $MVal = $TypeAttr{"Memb"}{$Pos}{"value"};
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04003751 $EnumConstants{$Version}{$MName} = {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04003752 "Value"=>$MVal,
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04003753 "Header"=>$TypeAttr{"Header"}
3754 };
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04003755 if(isAnon($TypeAttr{"Name"}))
3756 {
3757 %{$Constants{$Version}{$MName}} = (
3758 "Value" => $MVal,
3759 "Header" => $TypeAttr{"Header"}
3760 );
3761 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04003762 }
3763 }
3764 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003765 if($ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003766 {
3767 if(defined $TypedefToAnon{$TypeId}) {
3768 $TypeAttr{"AnonTypedef"} = 1;
3769 }
3770 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04003771
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003772 return %TypeAttr;
3773}
3774
3775sub detect_lang($)
3776{
3777 my $TypeId = $_[0];
3778 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003779 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003780 { # GCC 4 fncs-node points to only non-artificial methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003781 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /);
3782 }
3783 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003784 { # GCC 3
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003785 my $Fncs = getTreeAttr_Fncs($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003786 while($Fncs)
3787 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003788 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003789 return 1;
3790 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003791 $Fncs = getTreeAttr_Chan($Fncs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003792 }
3793 }
3794 return 0;
3795}
3796
3797sub setSpec($$)
3798{
3799 my ($TypeId, $TypeAttr) = @_;
3800 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3801 if($Info=~/\s+spec\s+/) {
3802 $TypeAttr->{"Spec"} = 1;
3803 }
3804}
3805
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003806sub setBaseClasses($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003807{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003808 my ($TypeId, $TypeAttr) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003809 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3810 if($Info=~/binf[ ]*:[ ]*@(\d+) /)
3811 {
3812 $Info = $LibInfo{$Version}{"info"}{$1};
3813 my $Pos = 0;
3814 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //)
3815 {
3816 my ($Access, $BInfoId) = ($1, $2);
3817 my $ClassId = getBinfClassId($BInfoId);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003818 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId};
3819 if(not $CType or $CType eq "template_type_parm"
3820 or $CType eq "typename_type")
3821 { # skip
3822 return 1;
3823 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003824 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId};
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003825 if($Access=~/prot/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003826 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected";
3827 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003828 elsif($Access=~/priv/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003829 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private";
3830 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003831 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003832 if($BaseInfo=~/virt/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003833 { # virtual base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003834 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1;
3835 }
3836 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003837 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003838 }
3839 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003840 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003841}
3842
3843sub getBinfClassId($)
3844{
3845 my $Info = $LibInfo{$Version}{"info"}{$_[0]};
3846 $Info=~/type[ ]*:[ ]*@(\d+) /;
3847 return $1;
3848}
3849
3850sub unmangledFormat($$)
3851{
3852 my ($Name, $LibVersion) = @_;
3853 $Name = uncover_typedefs($Name, $LibVersion);
3854 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){};
3855 $Name=~s/\(\w+\)(\d)/$1/;
3856 return $Name;
3857}
3858
3859sub modelUnmangled($$)
3860{
3861 my ($InfoId, $Compiler) = @_;
3862 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) {
3863 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId};
3864 }
3865 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
3866 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
3867 $PureSignature = "~".$PureSignature;
3868 }
3869 if(not $SymbolInfo{$Version}{$InfoId}{"Data"})
3870 {
3871 my (@Params, @ParamTypes) = ();
3872 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"}
3873 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
3874 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}});
3875 }
3876 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
3877 { # checking parameters
3878 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003879 my %PType = get_PureType($PId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003880 my $PTName = unmangledFormat($PType{"Name"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003881 $PTName=~s/\b(restrict|register)\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003882 if($Compiler eq "MSVC") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003883 $PTName=~s/\blong long\b/__int64/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003884 }
3885 @ParamTypes = (@ParamTypes, $PTName);
3886 }
3887 if(@ParamTypes) {
3888 $PureSignature .= "(".join(", ", @ParamTypes).")";
3889 }
3890 else
3891 {
3892 if($Compiler eq "MSVC")
3893 {
3894 $PureSignature .= "(void)";
3895 }
3896 else
3897 { # GCC
3898 $PureSignature .= "()";
3899 }
3900 }
3901 $PureSignature = delete_keywords($PureSignature);
3902 }
3903 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3904 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003905 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003906 $PureSignature = $ClassName."::".$PureSignature;
3907 }
3908 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) {
3909 $PureSignature = $NS."::".$PureSignature;
3910 }
3911 if($SymbolInfo{$Version}{$InfoId}{"Const"}) {
3912 $PureSignature .= " const";
3913 }
3914 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) {
3915 $PureSignature .= " volatile";
3916 }
3917 my $ShowReturn = 0;
3918 if($Compiler eq "MSVC"
3919 and $SymbolInfo{$Version}{$InfoId}{"Data"})
3920 {
3921 $ShowReturn=1;
3922 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003923 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId}
3924 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003925 {
3926 $ShowReturn=1;
3927 }
3928 if($ShowReturn)
3929 { # mangled names for template function specializations include return value
3930 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
3931 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003932 my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003933 my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
3934 $PureSignature = $ReturnName." ".$PureSignature;
3935 }
3936 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003937 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature, "S"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003938}
3939
3940sub mangle_symbol($$$)
3941{ # mangling for simple methods
3942 # see gcc-4.6.0/gcc/cp/mangle.c
3943 my ($InfoId, $LibVersion, $Compiler) = @_;
3944 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) {
3945 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler};
3946 }
3947 my $Mangled = "";
3948 if($Compiler eq "GCC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003949 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003950 }
3951 elsif($Compiler eq "MSVC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003952 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003953 }
3954 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled);
3955}
3956
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003957sub mangle_symbol_MSVC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003958{
3959 my ($InfoId, $LibVersion) = @_;
3960 return "";
3961}
3962
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003963sub mangle_symbol_GCC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003964{ # see gcc-4.6.0/gcc/cp/mangle.c
3965 my ($InfoId, $LibVersion) = @_;
3966 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003967 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003968 my %Repl = ();# SN_ replacements
3969 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
3970 {
3971 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl);
3972 if($MangledClass!~/\AN/) {
3973 $MangledClass = "N".$MangledClass;
3974 }
3975 else {
3976 $MangledClass=~s/E\Z//;
3977 }
3978 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) {
3979 $MangledClass=~s/\AN/NV/;
3980 }
3981 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) {
3982 $MangledClass=~s/\AN/NK/;
3983 }
3984 $Mangled .= $MangledClass;
3985 }
3986 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"})
3987 { # mangled by name due to the absence of structured info
3988 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl);
3989 if($MangledNS!~/\AN/) {
3990 $MangledNS = "N".$MangledNS;
3991 }
3992 else {
3993 $MangledNS=~s/E\Z//;
3994 }
3995 $Mangled .= $MangledNS;
3996 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04003997 my ($ShortName, $TmplParams) = template_Base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003998 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003999 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004000 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004001 foreach (@TPos) {
4002 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"});
4003 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004004 }
4005 elsif($TmplParams)
4006 { # remangling mode
4007 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004008 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004009 }
4010 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) {
4011 $Mangled .= "C1";
4012 }
4013 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4014 $Mangled .= "D0";
4015 }
4016 elsif($ShortName)
4017 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004018 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4019 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004020 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004021 and isConstType($Return, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004022 { # "const" global data is mangled as _ZL...
4023 $Mangled .= "L";
4024 }
4025 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004026 if($ShortName=~/\Aoperator(\W.*)\Z/)
4027 {
4028 my $Op = $1;
4029 $Op=~s/\A[ ]+//g;
4030 if(my $OpMngl = $OperatorMangling{$Op}) {
4031 $Mangled .= $OpMngl;
4032 }
4033 else { # conversion operator
4034 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl);
4035 }
4036 }
4037 else {
4038 $Mangled .= length($ShortName).$ShortName;
4039 }
4040 if(@TParams)
4041 { # templates
4042 $Mangled .= "I";
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04004043 foreach my $TParam (@TParams) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004044 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl);
4045 }
4046 $Mangled .= "E";
4047 }
4048 if(not $ClassId and @TParams) {
4049 add_substitution($ShortName, \%Repl, 0);
4050 }
4051 }
4052 if($ClassId or $NameSpace) {
4053 $Mangled .= "E";
4054 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004055 if(@TParams)
4056 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004057 if($Return) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004058 $Mangled .= mangle_param($Return, $LibVersion, \%Repl);
4059 }
4060 }
4061 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4062 {
4063 my @Params = ();
4064 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
4065 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4066 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
4067 }
4068 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4069 { # checking parameters
4070 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"};
4071 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl);
4072 }
4073 if(not @Params) {
4074 $Mangled .= "v";
4075 }
4076 }
4077 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled);
4078 $Mangled = write_stdcxx_substitution($Mangled);
4079 if($Mangled eq "_Z") {
4080 return "";
4081 }
4082 return $Mangled;
4083}
4084
4085sub correct_incharge($$$)
4086{
4087 my ($InfoId, $LibVersion, $Mangled) = @_;
4088 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"})
4089 {
4090 if($MangledNames{$LibVersion}{$Mangled}) {
4091 $Mangled=~s/C1E/C2E/;
4092 }
4093 }
4094 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
4095 {
4096 if($MangledNames{$LibVersion}{$Mangled}) {
4097 $Mangled=~s/D0E/D1E/;
4098 }
4099 if($MangledNames{$LibVersion}{$Mangled}) {
4100 $Mangled=~s/D1E/D2E/;
4101 }
4102 }
4103 return $Mangled;
4104}
4105
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004106sub template_Base($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004107{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004108 # NOTE: operators: >>, <<
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004109 my $Name = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004110 if($Name!~/>\Z/ or $Name!~/</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004111 return $Name;
4112 }
4113 my $TParams = $Name;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004114 while(my $CPos = find_center($TParams, "<"))
4115 { # search for the last <T>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004116 $TParams = substr($TParams, $CPos);
4117 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004118 if($TParams=~s/\A<(.+)>\Z/$1/) {
4119 $Name=~s/<\Q$TParams\E>\Z//;
4120 }
4121 else
4122 { # error
4123 $TParams = "";
4124 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004125 return ($Name, $TParams);
4126}
4127
4128sub get_sub_ns($)
4129{
4130 my $Name = $_[0];
4131 my @NS = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004132 while(my $CPos = find_center($Name, ":"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004133 {
4134 push(@NS, substr($Name, 0, $CPos));
4135 $Name = substr($Name, $CPos);
4136 $Name=~s/\A:://;
4137 }
4138 return (join("::", @NS), $Name);
4139}
4140
4141sub mangle_ns($$$)
4142{
4143 my ($Name, $LibVersion, $Repl) = @_;
4144 if(my $Tid = $TName_Tid{$LibVersion}{$Name})
4145 {
4146 my $Mangled = mangle_param($Tid, $LibVersion, $Repl);
4147 $Mangled=~s/\AN(.+)E\Z/$1/;
4148 return $Mangled;
4149
4150 }
4151 else
4152 {
4153 my ($MangledNS, $SubNS) = ("", "");
4154 ($SubNS, $Name) = get_sub_ns($Name);
4155 if($SubNS) {
4156 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4157 }
4158 $MangledNS .= length($Name).$Name;
4159 add_substitution($MangledNS, $Repl, 0);
4160 return $MangledNS;
4161 }
4162}
4163
4164sub mangle_param($$$)
4165{
4166 my ($PTid, $LibVersion, $Repl) = @_;
4167 my ($MPrefix, $Mangled) = ("", "");
4168 my %ReplCopy = %{$Repl};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004169 my %BaseType = get_BaseType($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004170 my $BaseType_Name = $BaseType{"Name"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004171 $BaseType_Name=~s/\A(struct|union|enum) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004172 if(not $BaseType_Name) {
4173 return "";
4174 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004175 my ($ShortName, $TmplParams) = template_Base($BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004176 my $Suffix = get_BaseTypeQual($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004177 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){};
4178 while($Suffix=~/(&|\*|const)\Z/)
4179 {
4180 if($Suffix=~s/[ ]*&\Z//) {
4181 $MPrefix .= "R";
4182 }
4183 if($Suffix=~s/[ ]*\*\Z//) {
4184 $MPrefix .= "P";
4185 }
4186 if($Suffix=~s/[ ]*const\Z//)
4187 {
4188 if($MPrefix=~/R|P/
4189 or $Suffix=~/&|\*/) {
4190 $MPrefix .= "K";
4191 }
4192 }
4193 if($Suffix=~s/[ ]*volatile\Z//) {
4194 $MPrefix .= "V";
4195 }
4196 #if($Suffix=~s/[ ]*restrict\Z//) {
4197 #$MPrefix .= "r";
4198 #}
4199 }
4200 if(my $Token = $IntrinsicMangling{$BaseType_Name}) {
4201 $Mangled .= $Token;
4202 }
4203 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/)
4204 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004205 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004206 if(my @TPos = keys(%{$BaseType{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004207 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004208 foreach (@TPos) {
4209 push(@TParams, $BaseType{"TParam"}{$_}{"name"});
4210 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004211 }
4212 elsif($TmplParams)
4213 { # remangling mode
4214 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004215 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004216 }
4217 my $MangledNS = "";
4218 my ($SubNS, $SName) = get_sub_ns($ShortName);
4219 if($SubNS) {
4220 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4221 }
4222 $MangledNS .= length($SName).$SName;
4223 if(@TParams) {
4224 add_substitution($MangledNS, $Repl, 0);
4225 }
4226 $Mangled .= "N".$MangledNS;
4227 if(@TParams)
4228 { # templates
4229 $Mangled .= "I";
4230 foreach my $TParam (@TParams) {
4231 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl);
4232 }
4233 $Mangled .= "E";
4234 }
4235 $Mangled .= "E";
4236 }
4237 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/)
4238 {
4239 if($BaseType{"Type"} eq "MethodPtr") {
4240 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F";
4241 }
4242 else {
4243 $Mangled .= "PF";
4244 }
4245 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4246 my @Params = keys(%{$BaseType{"Param"}});
4247 foreach my $Num (sort {int($a)<=>int($b)} @Params) {
4248 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl);
4249 }
4250 if(not @Params) {
4251 $Mangled .= "v";
4252 }
4253 $Mangled .= "E";
4254 }
4255 elsif($BaseType{"Type"} eq "FieldPtr")
4256 {
4257 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl);
4258 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4259 }
4260 $Mangled = $MPrefix.$Mangled;# add prefix (RPK)
4261 if(my $Optimized = write_substitution($Mangled, \%ReplCopy))
4262 {
4263 if($Mangled eq $Optimized)
4264 {
4265 if($ShortName!~/::/)
4266 { # remove "N ... E"
4267 if($MPrefix) {
4268 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g;
4269 }
4270 else {
4271 $Mangled=~s/\AN(.+)E\Z/$1/g;
4272 }
4273 }
4274 }
4275 else {
4276 $Mangled = $Optimized;
4277 }
4278 }
4279 add_substitution($Mangled, $Repl, 1);
4280 return $Mangled;
4281}
4282
4283sub mangle_template_param($$$)
4284{ # types + literals
4285 my ($TParam, $LibVersion, $Repl) = @_;
4286 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) {
4287 return mangle_param($TPTid, $LibVersion, $Repl);
4288 }
4289 elsif($TParam=~/\A(\d+)(\w+)\Z/)
4290 { # class_name<1u>::method(...)
4291 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E";
4292 }
4293 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/)
4294 { # class_name<(signed char)1>::method(...)
4295 return "L".$IntrinsicMangling{$1}.$2."E";
4296 }
4297 elsif($TParam eq "true")
4298 { # class_name<true>::method(...)
4299 return "Lb1E";
4300 }
4301 elsif($TParam eq "false")
4302 { # class_name<true>::method(...)
4303 return "Lb0E";
4304 }
4305 else { # internal error
4306 return length($TParam).$TParam;
4307 }
4308}
4309
4310sub add_substitution($$$)
4311{
4312 my ($Value, $Repl, $Rec) = @_;
4313 if($Rec)
4314 { # subtypes
4315 my @Subs = ($Value);
4316 while($Value=~s/\A(R|P|K)//) {
4317 push(@Subs, $Value);
4318 }
4319 foreach (reverse(@Subs)) {
4320 add_substitution($_, $Repl, 0);
4321 }
4322 return;
4323 }
4324 return if($Value=~/\AS(\d*)_\Z/);
4325 $Value=~s/\AN(.+)E\Z/$1/g;
4326 return if(defined $Repl->{$Value});
4327 return if(length($Value)<=1);
4328 return if($StdcxxMangling{$Value});
4329 # check for duplicates
4330 my $Base = $Value;
4331 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4332 {
4333 my $Num = $Repl->{$Type};
4334 my $Replace = macro_mangle($Num);
4335 $Base=~s/\Q$Replace\E/$Type/;
4336 }
4337 if(my $OldNum = $Repl->{$Base})
4338 {
4339 $Repl->{$Value} = $OldNum;
4340 return;
4341 }
4342 my @Repls = sort {$b<=>$a} values(%{$Repl});
4343 if(@Repls) {
4344 $Repl->{$Value} = $Repls[0]+1;
4345 }
4346 else {
4347 $Repl->{$Value} = -1;
4348 }
4349 # register duplicates
4350 # upward
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004351 $Base = $Value;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004352 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4353 {
4354 next if($Base eq $Type);
4355 my $Num = $Repl->{$Type};
4356 my $Replace = macro_mangle($Num);
4357 $Base=~s/\Q$Type\E/$Replace/;
4358 $Repl->{$Base} = $Repl->{$Value};
4359 }
4360}
4361
4362sub macro_mangle($)
4363{
4364 my $Num = $_[0];
4365 if($Num==-1) {
4366 return "S_";
4367 }
4368 else
4369 {
4370 my $Code = "";
4371 if($Num<10)
4372 { # S0_, S1_, S2_, ...
4373 $Code = $Num;
4374 }
4375 elsif($Num>=10 and $Num<=35)
4376 { # SA_, SB_, SC_, ...
4377 $Code = chr(55+$Num);
4378 }
4379 else
4380 { # S10_, S11_, S12_
4381 $Code = $Num-26; # 26 is length of english alphabet
4382 }
4383 return "S".$Code."_";
4384 }
4385}
4386
4387sub write_stdcxx_substitution($)
4388{
4389 my $Mangled = $_[0];
4390 if($StdcxxMangling{$Mangled}) {
4391 return $StdcxxMangling{$Mangled};
4392 }
4393 else
4394 {
4395 my @Repls = keys(%StdcxxMangling);
4396 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4397 foreach my $MangledType (@Repls)
4398 {
4399 my $Replace = $StdcxxMangling{$MangledType};
4400 #if($Mangled!~/$Replace/) {
4401 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4402 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4403 #}
4404 }
4405 }
4406 return $Mangled;
4407}
4408
4409sub write_substitution($$)
4410{
4411 my ($Mangled, $Repl) = @_;
4412 if(defined $Repl->{$Mangled}
4413 and my $MnglNum = $Repl->{$Mangled}) {
4414 $Mangled = macro_mangle($MnglNum);
4415 }
4416 else
4417 {
4418 my @Repls = keys(%{$Repl});
4419 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls;
4420 # FIXME: how to apply replacements? by num or by pos
4421 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4422 foreach my $MangledType (@Repls)
4423 {
4424 my $Replace = macro_mangle($Repl->{$MangledType});
4425 if($Mangled!~/$Replace/) {
4426 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4427 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4428 }
4429 }
4430 }
4431 return $Mangled;
4432}
4433
4434sub delete_keywords($)
4435{
4436 my $TypeName = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004437 $TypeName=~s/\b(enum|struct|union|class) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004438 return $TypeName;
4439}
4440
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004441sub uncover_typedefs($$)
4442{
4443 my ($TypeName, $LibVersion) = @_;
4444 return "" if(not $TypeName);
4445 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) {
4446 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName};
4447 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004448 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName, "T"), "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004449 while($TypeName_New ne $TypeName_Pre)
4450 {
4451 $TypeName_Pre = $TypeName_New;
4452 my $TypeName_Copy = $TypeName_New;
4453 my %Words = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004454 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004455 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004456 if(not $Intrinsic_Keywords{$1}) {
4457 $Words{$1} = 1;
4458 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004459 }
4460 foreach my $Word (keys(%Words))
4461 {
4462 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word};
4463 next if(not $BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004464 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004465 if($BaseType_Name=~/\([\*]+\)/)
4466 { # FuncPtr
4467 if($TypeName_New=~/\Q$Word\E(.*)\Z/)
4468 {
4469 my $Type_Suffix = $1;
4470 $TypeName_New = $BaseType_Name;
4471 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004472 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004473 }
4474 }
4475 }
4476 else
4477 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004478 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004479 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004480 }
4481 }
4482 }
4483 }
4484 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New);
4485}
4486
4487sub isInternal($)
4488{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004489 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4490 {
4491 if($Info=~/mngl[ ]*:[ ]*@(\d+) /)
4492 {
4493 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/)
4494 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL*
4495 return 1;
4496 }
4497 }
4498 }
4499 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004500}
4501
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004502sub getDataVal($$)
4503{
4504 my ($InfoId, $TypeId) = @_;
4505 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4506 {
4507 if($Info=~/init[ ]*:[ ]*@(\d+) /)
4508 {
4509 if(defined $LibInfo{$Version}{"info_type"}{$1}
4510 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004511 {
4512 if(my $Nop = getTreeAttr_Op($1))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004513 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004514 if(defined $LibInfo{$Version}{"info_type"}{$Nop}
4515 and $LibInfo{$Version}{"info_type"}{$Nop} eq "addr_expr")
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004516 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004517 if(my $Addr = getTreeAttr_Op($1)) {
4518 return getInitVal($Addr, $TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004519 }
4520 }
4521 }
4522 }
4523 else {
4524 return getInitVal($1, $TypeId);
4525 }
4526 }
4527 }
4528 return undef;
4529}
4530
4531sub getInitVal($$)
4532{
4533 my ($InfoId, $TypeId) = @_;
4534 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4535 {
4536 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId})
4537 {
4538 if($InfoType eq "integer_cst")
4539 {
4540 my $Val = getNodeIntCst($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004541 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004542 { # characters
4543 $Val = chr($Val);
4544 }
4545 return $Val;
4546 }
4547 elsif($InfoType eq "string_cst") {
4548 return getNodeStrCst($InfoId);
4549 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004550 elsif($InfoType eq "var_decl")
4551 {
4552 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) {
4553 return $Name;
4554 }
4555 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004556 }
4557 }
4558 return undef;
4559}
4560
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004561sub set_Class_And_Namespace($)
4562{
4563 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004564 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004565 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004566 if($Info=~/scpe[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004567 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004568 my $NSInfoId = $1;
4569 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
4570 {
4571 if($InfoType eq "namespace_decl") {
4572 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId);
4573 }
4574 elsif($InfoType eq "record_type") {
4575 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId;
4576 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004577 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004578 }
4579 }
4580 if($SymbolInfo{$Version}{$InfoId}{"Class"}
4581 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004582 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004583 if($COMMON_LANGUAGE{$Version} ne "C++")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004584 { # skip
4585 return 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004586 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004587 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004588
4589 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004590}
4591
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004592sub debugMangling($)
4593{
4594 my $LibVersion = $_[0];
4595 my %Mangled = ();
4596 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
4597 {
4598 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
4599 {
4600 if($Mngl=~/\A(_Z|\?)/) {
4601 $Mangled{$Mngl}=$InfoId;
4602 }
4603 }
4604 }
4605 translateSymbols(keys(%Mangled), $LibVersion);
4606 foreach my $Mngl (keys(%Mangled))
4607 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004608 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC");
4609 my $U2 = $tr_name{$Mngl};
4610 if($U1 ne $U2) {
4611 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004612 }
4613 }
4614}
4615
4616sub linkSymbol($)
4617{ # link symbols from shared libraries
4618 # with the symbols from header files
4619 my $InfoId = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004620 # try to mangle symbol
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004621 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"})
4622 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004623 { # 1. GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
4624 # 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 +04004625 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004626 {
4627 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
4628 return correct_incharge($InfoId, $Version, $Mangled);
4629 }
4630 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004631 if($CheckHeadersOnly
4632 or not $BinaryOnly)
4633 { # 1. --headers-only mode
4634 # 2. not mangled src-only symbols
4635 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) {
4636 return $Mangled;
4637 }
4638 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004639 }
4640 return "";
4641}
4642
4643sub setLanguage($$)
4644{
4645 my ($LibVersion, $Lang) = @_;
4646 if(not $UserLang) {
4647 $COMMON_LANGUAGE{$LibVersion} = $Lang;
4648 }
4649}
4650
4651sub getSymbolInfo($)
4652{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004653 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004654 if(isInternal($InfoId)) {
4655 return;
4656 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004657 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
4658 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004659 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"}))
4660 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004661 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004662 return;
4663 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004664 setFuncAccess($InfoId);
4665 setFuncKind($InfoId);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004666 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"})
4667 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004668 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004669 return;
4670 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004671
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004672 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004673 if($SymbolInfo{$Version}{$InfoId}{"Return"} = getFuncReturn($InfoId))
4674 {
4675 if(not $TypeInfo{$Version}{$SymbolInfo{$Version}{$InfoId}{"Return"}}{"Name"})
4676 { # templates
4677 delete($SymbolInfo{$Version}{$InfoId});
4678 return;
4679 }
4680 }
4681 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
4682 {
4683 if(defined $MissedTypedef{$Version}{$Rid})
4684 {
4685 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
4686 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
4687 }
4688 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004689 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004690 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) {
4691 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004692 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004693 my $Orig = getFuncOrig($InfoId);
4694 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004695 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "\._")!=-1)
4696 {
4697 delete($SymbolInfo{$Version}{$InfoId});
4698 return;
4699 }
4700
4701 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "tmp_add_func")==0)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004702 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004703 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004704 return;
4705 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004706
4707 if(defined $TemplateInstance{$Version}{"Func"}{$Orig})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004708 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004709 my @TParams = getTParams($Orig, "Func");
4710 if(not @TParams)
4711 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004712 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004713 return;
4714 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004715 foreach my $Pos (0 .. $#TParams) {
4716 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"}=$TParams[$Pos];
4717 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004718 my $PrmsInLine = join(", ", @TParams);
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004719 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/)
4720 { # operator<< <T>, operator>> <T>
4721 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " ";
4722 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004723 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".$PrmsInLine.">";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004724 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "S");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004725 }
4726 else
4727 { # support for GCC 3.4
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004728 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004729 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004730 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
4731 {
4732 if($OSgroup eq "windows")
4733 { # cut the offset
4734 $MnglName=~s/\@\d+\Z//g;
4735 }
4736 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
4737
4738 # NOTE: mangling of some symbols may change depending on GCC version
4739 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
4740 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
4741 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004742
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004743 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004744 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004745 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004746 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004747 return;
4748 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004749 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004750 { # destructors have an empty parameter list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004751 my $Skip = setFuncParams($InfoId);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004752 if($Skip)
4753 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004754 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004755 return;
4756 }
4757 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004758 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) {
4759 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1;
4760 }
4761
4762 if(set_Class_And_Namespace($InfoId))
4763 {
4764 delete($SymbolInfo{$Version}{$InfoId});
4765 return;
4766 }
4767
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004768 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
4769 {
4770 if(not $TypeInfo{$Version}{$ClassId}{"Name"})
4771 { # templates
4772 delete($SymbolInfo{$Version}{$InfoId});
4773 return;
4774 }
4775 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004776 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
4777 { # extern "C"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004778 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004779 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004780 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004781 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004782 { # --lang=C option
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004783 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004784 }
4785 if($COMMON_LANGUAGE{$Version} eq "C++")
4786 { # correct mangled & short names
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004787 # C++ or --headers-only mode
4788 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004789 { # support for old GCC versions: reconstruct real names for constructors and destructors
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004790 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"}));
4791 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004792 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004793 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004794 { # try to mangle symbol (link with libraries)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004795 if(my $Mangled = linkSymbol($InfoId)) {
4796 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004797 }
4798 }
4799 if($OStarget eq "windows")
4800 { # link MS C++ symbols from library with GCC symbols from headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004801 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004802 { # exported symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004803 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004804 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004805 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004806 { # pure virtual symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004807 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004808 }
4809 }
4810 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004811 else
4812 { # not mangled in C
4813 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4814 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004815 if(not $CheckHeadersOnly
4816 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function"
4817 and not $SymbolInfo{$Version}{$InfoId}{"Class"})
4818 {
4819 my $Incorrect = 0;
4820
4821 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
4822 {
4823 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")==0
4824 and not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
4825 { # mangled in the TU dump, but not mangled in the library
4826 $Incorrect = 1;
4827 }
4828 }
4829 else
4830 {
4831 if($SymbolInfo{$Version}{$InfoId}{"Lang"} ne "C")
4832 { # all C++ functions are not mangled in the TU dump
4833 $Incorrect = 1;
4834 }
4835 }
4836 if($Incorrect)
4837 {
4838 if(link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps")) {
4839 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4840 }
4841 }
4842 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004843 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004844 { # can't detect symbol name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004845 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004846 return;
4847 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004848 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004849 and my $Spec = getVirtSpec($Orig))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004850 { # identify virtual and pure virtual functions
4851 # NOTE: constructors cannot be virtual
4852 # NOTE: in GCC 4.7 D1 destructors have no virtual spec
4853 # in the TU dump, so taking it from the original symbol
4854 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"}
4855 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/))
4856 { # NOTE: D2 destructors are not present in a v-table
4857 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1;
4858 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004859 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004860 if(isInline($InfoId)) {
4861 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004862 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004863 if(hasThrow($InfoId)) {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04004864 $SymbolInfo{$Version}{$InfoId}{"Throw"} = 1;
4865 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004866 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
4867 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004868 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004869 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"}
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04004870 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004871 { # inline or auto-generated constructor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004872 delete($TypeInfo{$Version}{$ClassId}{"Copied"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004873 }
4874 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004875 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
4876 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004877 if(not $ExtraDump)
4878 {
4879 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
4880 { # non-target symbols
4881 delete($SymbolInfo{$Version}{$InfoId});
4882 return;
4883 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004884 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004885 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004886 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method"
4887 or $SymbolInfo{$Version}{$InfoId}{"Constructor"}
4888 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}
4889 or $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004890 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004891 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/)
4892 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004893 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004894 return;
4895 }
4896 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004897 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004898 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004899 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004900 { # one instance for one mangled name only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004901 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004902 return;
4903 }
4904 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004905 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004906 }
4907 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004908 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
4909 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4910 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004911 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004912 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/
4913 and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004914 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004915 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004916 { # static methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004917 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004918 }
4919 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004920 if(getFuncLink($InfoId) eq "Static") {
4921 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004922 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004923 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/)
4924 {
4925 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
4926 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004927 if($Unmangled=~/\.\_\d/)
4928 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004929 delete($SymbolInfo{$Version}{$InfoId});
4930 return;
4931 }
4932 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004933 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004934 delete($SymbolInfo{$Version}{$InfoId}{"Type"});
4935 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) {
4936 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004937 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004938 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) {
4939 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004940 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004941
4942 if($WeakSymbols{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) {
4943 $SymbolInfo{$Version}{$InfoId}{"Weak"} = 1;
4944 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004945
4946 if($ExtraDump) {
4947 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
4948 }
4949}
4950
4951sub guessHeader($)
4952{
4953 my $InfoId = $_[0];
4954 my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4955 my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"};
4956 my $ClassName = $ClassId?get_ShortClass($ClassId, $Version):"";
4957 my $Header = $SymbolInfo{$Version}{$InfoId}{"Header"};
4958 if(my $HPath = $SymbolHeader{$Version}{$ClassName}{$ShortName})
4959 {
4960 if(get_filename($HPath) eq $Header)
4961 {
4962 my $HDir = get_filename(get_dirname($HPath));
4963 if($HDir ne "include"
4964 and $HDir=~/\A[a-z]+\Z/i) {
4965 return join_P($HDir, $Header);
4966 }
4967 }
4968 }
4969 return $Header;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004970}
4971
4972sub isInline($)
4973{ # "body: undefined" in the tree
4974 # -fkeep-inline-functions GCC option should be specified
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004975 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4976 {
4977 if($Info=~/ undefined /i) {
4978 return 0;
4979 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004980 }
4981 return 1;
4982}
4983
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04004984sub hasThrow($)
4985{
4986 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4987 {
4988 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
4989 return getTreeAttr_Unql($1, "unql");
4990 }
4991 }
4992 return 1;
4993}
4994
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004995sub getTypeId($)
4996{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004997 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4998 {
4999 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5000 return $1;
5001 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005002 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005003 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005004}
5005
5006sub setTypeMemb($$)
5007{
5008 my ($TypeId, $TypeAttr) = @_;
5009 my $TypeType = $TypeAttr->{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005010 my ($Pos, $UnnamedPos) = (0, 0);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005011 my $StaticFields = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005012 if($TypeType eq "Enum")
5013 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005014 my $MInfoId = getTreeAttr_Csts($TypeId);
5015 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005016 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005017 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId);
5018 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005019 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005020 $EnumMembName_Id{$Version}{getTreeAttr_Valu($MInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
5021 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005022 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005023 }
5024 }
5025 elsif($TypeType=~/\A(Struct|Class|Union)\Z/)
5026 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005027 my $MInfoId = getTreeAttr_Flds($TypeId);
5028 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005029 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005030 my $IType = $LibInfo{$Version}{"info_type"}{$MInfoId};
5031 my $MInfo = $LibInfo{$Version}{"info"}{$MInfoId};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005032 if(not $IType or $IType ne "field_decl")
5033 { # search for fields, skip other stuff in the declaration
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005034
5035 if($IType eq "var_decl")
5036 { # static field
5037 $StaticFields = 1;
5038 }
5039
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005040 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005041 next;
5042 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005043 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId));
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005044 if(index($StructMembName, "_vptr.")==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005045 { # virtual tables
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005046 $StructMembName = "_vptr";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005047 }
5048 if(not $StructMembName)
5049 { # unnamed fields
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005050 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005051 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005052 my $UnnamedTid = getTreeAttr_Type($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005053 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid));
5054 if(isAnon($UnnamedTName))
5055 { # rename unnamed fields to unnamed0, unnamed1, ...
5056 $StructMembName = "unnamed".($UnnamedPos++);
5057 }
5058 }
5059 }
5060 if(not $StructMembName)
5061 { # unnamed fields and base classes
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005062 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005063 next;
5064 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005065 my $MembTypeId = getTreeAttr_Type($MInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005066 if(defined $MissedTypedef{$Version}{$MembTypeId})
5067 {
5068 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) {
5069 $MembTypeId = $AddedTid;
5070 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005071 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005072 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId;
5073 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005074 if((my $Access = getTreeAccess($MInfoId)) ne "public")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005075 { # marked only protected and private, public by default
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005076 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access;
5077 }
5078 if($MInfo=~/spec:\s*mutable /)
5079 { # mutable fields
5080 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005081 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005082 if(my $Algn = getAlgn($MInfoId)) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005083 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
5084 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005085 if(my $BFSize = getBitField($MInfoId))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005086 { # in bits
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005087 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005088 }
5089 else
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005090 { # in bytes
5091 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005092 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005093
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005094 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005095 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005096 }
5097 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005098
5099 return $StaticFields;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005100}
5101
5102sub setFuncParams($)
5103{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005104 my $InfoId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005105 my $ParamInfoId = getTreeAttr_Args($InfoId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005106 if(getFuncType($InfoId) eq "Method")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005107 { # check type of "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005108 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId);
5109 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005110 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005111 if($ObjectName=~/\bconst(| volatile)\*const\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005112 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
5113 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005114 if($ObjectName=~/\bvolatile\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005115 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
5116 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005117 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005118 else
5119 { # skip
5120 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005121 }
5122 $ParamInfoId = getNextElem($ParamInfoId);
5123 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005124 my ($Pos, $Vtt_Pos) = (0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005125 while($ParamInfoId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005126 { # formal args
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005127 my $ParamTypeId = getTreeAttr_Type($ParamInfoId);
5128 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId));
5129 if(not $ParamName)
5130 { # unnamed
5131 $ParamName = "p".($Pos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005132 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005133 if(defined $MissedTypedef{$Version}{$ParamTypeId})
5134 {
5135 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) {
5136 $ParamTypeId = $AddedTid;
5137 }
5138 }
5139 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005140 if(not $PType or $PType eq "Unknown") {
5141 return 1;
5142 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005143 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005144 if(not $PTName) {
5145 return 1;
5146 }
5147 if($PTName eq "void") {
5148 last;
5149 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005150 if($ParamName eq "__vtt_parm"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005151 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005152 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005153 $Vtt_Pos = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005154 $ParamInfoId = getNextElem($ParamInfoId);
5155 next;
5156 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005157 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5158 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005159 if(my $Algn = getAlgn($ParamInfoId)) {
5160 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
5161 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005162 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"}) {
5163 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($Pos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005164 }
5165 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /)
5166 { # foo(register type arg)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005167 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005168 }
5169 $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005170 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005171 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005172 if(setFuncArgs($InfoId, $Vtt_Pos)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005173 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = "-1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005174 }
5175 return 0;
5176}
5177
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005178sub setFuncArgs($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005179{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005180 my ($InfoId, $Vtt_Pos) = @_;
5181 my $FuncTypeId = getFuncTypeId($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005182 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005183 if(getFuncType($InfoId) eq "Method") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005184 $ParamListElemId = getNextElem($ParamListElemId);
5185 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005186 if(not $ParamListElemId)
5187 { # foo(...)
5188 return 1;
5189 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005190 my $HaveVoid = 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005191 my $Pos = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005192 while($ParamListElemId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005193 { # actual params: may differ from formal args
5194 # formal int*const
5195 # actual: int*
5196 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005197 {
5198 $Vtt_Pos=-1;
5199 $ParamListElemId = getNextElem($ParamListElemId);
5200 next;
5201 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005202 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId);
5203 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005204 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005205 $HaveVoid = 1;
5206 last;
5207 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005208 elsif(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005209 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005210 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005211 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5212 { # unnamed
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005213 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($Pos+1);
5214 }
5215 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005216 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005217 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005218 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5219 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005220 if($PurpType eq "nop_expr")
5221 { # func ( const char* arg = (const char*)(void*)0 )
5222 $PurpId = getTreeAttr_Op($PurpId);
5223 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005224 my $Val = getInitVal($PurpId, $ParamTypeId);
5225 if(defined $Val) {
5226 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5227 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005228 }
5229 }
5230 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005231 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005232 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005233 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005234}
5235
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005236sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005237{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005238 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5239 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005240 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5241 return $1;
5242 }
5243 }
5244 return "";
5245}
5246
5247sub getTreeAttr_Chain($)
5248{
5249 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5250 {
5251 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5252 return $1;
5253 }
5254 }
5255 return "";
5256}
5257
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005258sub getTreeAttr_Unql($)
5259{
5260 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5261 {
5262 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5263 return $1;
5264 }
5265 }
5266 return "";
5267}
5268
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005269sub getTreeAttr_Scpe($)
5270{
5271 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5272 {
5273 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5274 return $1;
5275 }
5276 }
5277 return "";
5278}
5279
5280sub getTreeAttr_Type($)
5281{
5282 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5283 {
5284 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5285 return $1;
5286 }
5287 }
5288 return "";
5289}
5290
5291sub getTreeAttr_Name($)
5292{
5293 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5294 {
5295 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5296 return $1;
5297 }
5298 }
5299 return "";
5300}
5301
5302sub getTreeAttr_Mngl($)
5303{
5304 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5305 {
5306 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5307 return $1;
5308 }
5309 }
5310 return "";
5311}
5312
5313sub getTreeAttr_Prms($)
5314{
5315 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5316 {
5317 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5318 return $1;
5319 }
5320 }
5321 return "";
5322}
5323
5324sub getTreeAttr_Fncs($)
5325{
5326 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5327 {
5328 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5329 return $1;
5330 }
5331 }
5332 return "";
5333}
5334
5335sub getTreeAttr_Csts($)
5336{
5337 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5338 {
5339 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5340 return $1;
5341 }
5342 }
5343 return "";
5344}
5345
5346sub getTreeAttr_Purp($)
5347{
5348 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5349 {
5350 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5351 return $1;
5352 }
5353 }
5354 return "";
5355}
5356
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005357sub getTreeAttr_Op($)
5358{
5359 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5360 {
5361 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) {
5362 return $1;
5363 }
5364 }
5365 return "";
5366}
5367
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005368sub getTreeAttr_Valu($)
5369{
5370 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5371 {
5372 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5373 return $1;
5374 }
5375 }
5376 return "";
5377}
5378
5379sub getTreeAttr_Flds($)
5380{
5381 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5382 {
5383 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5384 return $1;
5385 }
5386 }
5387 return "";
5388}
5389
5390sub getTreeAttr_Args($)
5391{
5392 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5393 {
5394 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005395 return $1;
5396 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005397 }
5398 return "";
5399}
5400
5401sub getTreeValue($)
5402{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005403 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5404 {
5405 if($Info=~/low[ ]*:[ ]*([^ ]+) /) {
5406 return $1;
5407 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005408 }
5409 return "";
5410}
5411
5412sub getTreeAccess($)
5413{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005414 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005415 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005416 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5417 {
5418 my $Access = $1;
5419 if($Access eq "prot") {
5420 return "protected";
5421 }
5422 elsif($Access eq "priv") {
5423 return "private";
5424 }
5425 }
5426 elsif($Info=~/ protected /)
5427 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005428 return "protected";
5429 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005430 elsif($Info=~/ private /)
5431 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005432 return "private";
5433 }
5434 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005435 return "public";
5436}
5437
5438sub setFuncAccess($)
5439{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005440 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005441 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005442 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005443 }
5444 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005445 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005446 }
5447}
5448
5449sub setTypeAccess($$)
5450{
5451 my ($TypeId, $TypeAttr) = @_;
5452 my $Access = getTreeAccess($TypeId);
5453 if($Access eq "protected") {
5454 $TypeAttr->{"Protected"} = 1;
5455 }
5456 elsif($Access eq "private") {
5457 $TypeAttr->{"Private"} = 1;
5458 }
5459}
5460
5461sub setFuncKind($)
5462{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005463 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5464 {
5465 if($Info=~/pseudo tmpl/) {
5466 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
5467 }
5468 elsif($Info=~/ constructor /) {
5469 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
5470 }
5471 elsif($Info=~/ destructor /) {
5472 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
5473 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005474 }
5475}
5476
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005477sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005478{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005479 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5480 {
5481 if($Info=~/spec[ ]*:[ ]*pure /) {
5482 return "PureVirt";
5483 }
5484 elsif($Info=~/spec[ ]*:[ ]*virt /) {
5485 return "Virt";
5486 }
5487 elsif($Info=~/ pure\s+virtual /)
5488 { # support for old GCC versions
5489 return "PureVirt";
5490 }
5491 elsif($Info=~/ virtual /)
5492 { # support for old GCC versions
5493 return "Virt";
5494 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005495 }
5496 return "";
5497}
5498
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005499sub getFuncLink($)
5500{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005501 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5502 {
5503 if($Info=~/link[ ]*:[ ]*static /) {
5504 return "Static";
5505 }
5506 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005507 return $1;
5508 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005509 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005510 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005511}
5512
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005513sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005514{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005515 my ($Symbol, $LibVersion) = @_;
5516 return "" if(not $Symbol or not $LibVersion);
5517 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
5518 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005519 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005520 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
5521 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
5522 }
5523 }
5524 if($NS)
5525 {
5526 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5527 return $NS;
5528 }
5529 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005530 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005531 while($NS=~s/::[^:]+\Z//)
5532 {
5533 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5534 return $NS;
5535 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005536 }
5537 }
5538 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005539
5540 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005541}
5542
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005543sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005544{
5545 my ($TypeName, $LibVersion) = @_;
5546 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005547 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005548 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005549 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5550 return $NS;
5551 }
5552 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005553 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005554 while($NS=~s/::[^:]+\Z//)
5555 {
5556 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5557 return $NS;
5558 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005559 }
5560 }
5561 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005562 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005563}
5564
5565sub getNameSpace($)
5566{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005567 my $InfoId = $_[0];
5568 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005569 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005570 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005571 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005572 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005573 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005574 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
5575 {
5576 my $NameSpace = getTreeStr($1);
5577 if($NameSpace eq "::")
5578 { # global namespace
5579 return "";
5580 }
5581 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
5582 $NameSpace = $BaseNameSpace."::".$NameSpace;
5583 }
5584 $NestedNameSpaces{$Version}{$NameSpace} = 1;
5585 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005586 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005587 else {
5588 return "";
5589 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005590 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005591 elsif($InfoType eq "record_type")
5592 { # inside data type
5593 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
5594 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005595 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005596 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005597 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005598 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005599}
5600
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005601sub getEnumMembVal($)
5602{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005603 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005604 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005605 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
5606 {
5607 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
5608 {
5609 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
5610 { # in newer versions of GCC the value is in the "const_decl->cnst" node
5611 return getTreeValue($1);
5612 }
5613 else
5614 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
5615 return getTreeValue($1);
5616 }
5617 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005618 }
5619 }
5620 return "";
5621}
5622
5623sub getSize($)
5624{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005625 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5626 {
5627 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
5628 return getTreeValue($1);
5629 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005630 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005631 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005632}
5633
5634sub getAlgn($)
5635{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005636 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5637 {
5638 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
5639 return $1;
5640 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005641 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005642 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005643}
5644
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005645sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005646{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005647 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5648 {
5649 if($Info=~/ bitfield /) {
5650 return getSize($_[0]);
5651 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005652 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005653 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005654}
5655
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005656sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005657{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005658 if(my $Chan = getTreeAttr_Chan($_[0])) {
5659 return $Chan;
5660 }
5661 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
5662 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005663 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005664 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005665}
5666
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005667sub registerHeader($$)
5668{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005669 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005670 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005671 return "";
5672 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005673 if(is_abs($Header) and not -f $Header)
5674 { # incorrect absolute path
5675 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005676 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005677 if(skipHeader($Header, $LibVersion))
5678 { # skip
5679 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005680 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005681 if(my $Header_Path = identifyHeader($Header, $LibVersion))
5682 {
5683 detect_header_includes($Header_Path, $LibVersion);
5684
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005685 if(defined $Tolerance and $Tolerance=~/3/)
5686 { # 3 - skip headers that include non-Linux headers
5687 if($OSgroup ne "windows")
5688 {
5689 foreach my $Inc (keys(%{$Header_Includes{$LibVersion}{$Header_Path}}))
5690 {
5691 if(specificHeader($Inc, "windows")) {
5692 return "";
5693 }
5694 }
5695 }
5696 }
5697
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005698 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
5699 { # redirect
5700 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
5701 or skipHeader($RHeader_Path, $LibVersion))
5702 { # skip
5703 return "";
5704 }
5705 $Header_Path = $RHeader_Path;
5706 }
5707 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
5708 { # skip
5709 return "";
5710 }
5711
5712 if(my $HName = get_filename($Header_Path))
5713 { # register
5714 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
5715 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
5716 }
5717
5718 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
5719 or $Header!~/\.(\w+)\Z/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005720 { # hpp, hh, etc.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005721 setLanguage($LibVersion, "C++");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005722 $CPP_HEADERS = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005723 }
5724
5725 if($CheckHeadersOnly
5726 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
5727 { # /usr/include/c++/4.6.1/...
5728 $STDCXX_TESTING = 1;
5729 }
5730
5731 return $Header_Path;
5732 }
5733 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005734}
5735
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005736sub registerDir($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005737{
5738 my ($Dir, $WithDeps, $LibVersion) = @_;
5739 $Dir=~s/[\/\\]+\Z//g;
5740 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005741 $Dir = get_abs_path($Dir);
5742 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005743 if($WithDeps)
5744 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005745 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
5746 return;
5747 }
5748 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
5749 $Mode = "DepsOnly";
5750 }
5751 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005752 else
5753 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005754 if($RegisteredDirs{$LibVersion}{$Dir}{1}
5755 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
5756 return;
5757 }
5758 }
5759 $Header_Dependency{$LibVersion}{$Dir} = 1;
5760 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
5761 if($Mode eq "DepsOnly")
5762 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005763 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005764 $Header_Dependency{$LibVersion}{$Path} = 1;
5765 }
5766 return;
5767 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005768 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005769 {
5770 if($WithDeps)
5771 {
5772 my $SubDir = $Path;
5773 while(($SubDir = get_dirname($SubDir)) ne $Dir)
5774 { # register all sub directories
5775 $Header_Dependency{$LibVersion}{$SubDir} = 1;
5776 }
5777 }
5778 next if(is_not_header($Path));
5779 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005780 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005781 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005782 $Include_Neighbors{$LibVersion}{$Part} = $Path;
5783 }
5784 }
5785 if(get_filename($Dir) eq "include")
5786 { # search for "lib/include/" directory
5787 my $LibDir = $Dir;
5788 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005789 registerDir($LibDir, $WithDeps, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005790 }
5791 }
5792}
5793
5794sub parse_redirect($$$)
5795{
5796 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005797 my @Errors = ();
5798 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
5799 push(@Errors, $1);
5800 }
5801 my $Redirect = "";
5802 foreach (@Errors)
5803 {
5804 s/\s{2,}/ /g;
5805 if(/(only|must\ include
5806 |update\ to\ include
5807 |replaced\ with
5808 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005809 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005810 {
5811 $Redirect = $2;
5812 last;
5813 }
5814 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
5815 {
5816 $Redirect = $2;
5817 last;
5818 }
5819 elsif(/this\ header\ should\ not\ be\ used
5820 |programs\ should\ not\ directly\ include
5821 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
5822 |is\ not\ supported\ API\ for\ general\ use
5823 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005824 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005825 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
5826 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
5827 }
5828 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005829 if($Redirect)
5830 {
5831 $Redirect=~s/\A<//g;
5832 $Redirect=~s/>\Z//g;
5833 }
5834 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005835}
5836
5837sub parse_includes($$)
5838{
5839 my ($Content, $Path) = @_;
5840 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005841 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005842 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005843 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005844 my $Method = substr($Header, 0, 1, "");
5845 substr($Header, length($Header)-1, 1, "");
5846 $Header = path_format($Header, $OSgroup);
5847 if($Method eq "\"" or is_abs($Header))
5848 {
5849 if(-e join_P(get_dirname($Path), $Header))
5850 { # relative path exists
5851 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005852 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005853 else
5854 { # include "..." that doesn't exist is equal to include <...>
5855 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005856 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005857 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005858 else {
5859 $Includes{$Header} = 1;
5860 }
5861 }
5862 if($ExtraInfo)
5863 {
5864 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
5865 { # FT_FREETYPE_H
5866 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005867 }
5868 }
5869 return \%Includes;
5870}
5871
5872sub ignore_path($)
5873{
5874 my $Path = $_[0];
5875 if($Path=~/\~\Z/)
5876 {# skipping system backup files
5877 return 1;
5878 }
5879 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
5880 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
5881 return 1;
5882 }
5883 return 0;
5884}
5885
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005886sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005887{
5888 my ($ArrRef, $W) = @_;
5889 return if(length($W)<2);
5890 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
5891}
5892
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005893sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005894{
5895 my ($H1, $H2) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005896
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005897 $H1=~s/\.[a-z]+\Z//ig;
5898 $H2=~s/\.[a-z]+\Z//ig;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005899
5900 my $Hname1 = get_filename($H1);
5901 my $Hname2 = get_filename($H2);
5902 my $HDir1 = get_dirname($H1);
5903 my $HDir2 = get_dirname($H2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005904 my $Dirname1 = get_filename($HDir1);
5905 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005906
5907 $HDir1=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
5908 $HDir2=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
5909
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005910 if($_[0] eq $_[1]
5911 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005912 return 0;
5913 }
5914 elsif($H1=~/\A\Q$H2\E/) {
5915 return 1;
5916 }
5917 elsif($H2=~/\A\Q$H1\E/) {
5918 return -1;
5919 }
5920 elsif($HDir1=~/\Q$Hname1\E/i
5921 and $HDir2!~/\Q$Hname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005922 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005923 return -1;
5924 }
5925 elsif($HDir2=~/\Q$Hname2\E/i
5926 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005927 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005928 return 1;
5929 }
5930 elsif($Hname1=~/\Q$Dirname1\E/i
5931 and $Hname2!~/\Q$Dirname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005932 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005933 return -1;
5934 }
5935 elsif($Hname2=~/\Q$Dirname2\E/i
5936 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005937 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005938 return 1;
5939 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005940 elsif($Hname1=~/(config|lib|util)/i
5941 and $Hname2!~/(config|lib|util)/i)
5942 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005943 return -1;
5944 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005945 elsif($Hname2=~/(config|lib|util)/i
5946 and $Hname1!~/(config|lib|util)/i)
5947 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005948 return 1;
5949 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005950 else
5951 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005952 my $R1 = checkRelevance($H1);
5953 my $R2 = checkRelevance($H2);
5954 if($R1 and not $R2)
5955 { # libebook/e-book.h
5956 return -1;
5957 }
5958 elsif($R2 and not $R1)
5959 { # libebook/e-book.h
5960 return 1;
5961 }
5962 else
5963 {
5964 return (lc($H1) cmp lc($H2));
5965 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005966 }
5967}
5968
5969sub searchForHeaders($)
5970{
5971 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005972
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005973 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005974 registerGccHeaders();
5975
5976 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
5977 { # c++ standard include paths
5978 registerCppHeaders();
5979 }
5980
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005981 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005982 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
5983 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005984 {
5985 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005986 if($SystemRoot)
5987 {
5988 if(is_abs($Path)) {
5989 $Path = $SystemRoot.$Path;
5990 }
5991 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005992 if(not -e $Path) {
5993 exitStatus("Access_Error", "can't access \'$Path\'");
5994 }
5995 elsif(-f $Path) {
5996 exitStatus("Access_Error", "\'$Path\' - not a directory");
5997 }
5998 elsif(-d $Path)
5999 {
6000 $Path = get_abs_path($Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006001 registerDir($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006002 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
6003 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006004 }
6005 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006006 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006007 }
6008 }
6009 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006010 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006011 $INC_PATH_AUTODETECT{$LibVersion} = 0;
6012 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006013
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006014 # registering directories
6015 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6016 {
6017 next if(not -e $Path);
6018 $Path = get_abs_path($Path);
6019 $Path = path_format($Path, $OSgroup);
6020 if(-d $Path) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006021 registerDir($Path, 1, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006022 }
6023 elsif(-f $Path)
6024 {
6025 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006026 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006027 and not $LocalIncludes{$Dir})
6028 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006029 registerDir($Dir, 1, $LibVersion);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006030 # if(my $OutDir = get_dirname($Dir))
6031 # { # registering the outer directory
6032 # if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
6033 # and not $LocalIncludes{$OutDir}) {
6034 # registerDir($OutDir, 0, $LibVersion);
6035 # }
6036 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006037 }
6038 }
6039 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006040
6041 # clean memory
6042 %RegisteredDirs = ();
6043
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006044 # registering headers
6045 my $Position = 0;
6046 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6047 {
6048 if(is_abs($Dest) and not -e $Dest) {
6049 exitStatus("Access_Error", "can't access \'$Dest\'");
6050 }
6051 $Dest = path_format($Dest, $OSgroup);
6052 if(is_header($Dest, 1, $LibVersion))
6053 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006054 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006055 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
6056 }
6057 }
6058 elsif(-d $Dest)
6059 {
6060 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006061 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006062 {
6063 next if(ignore_path($Path));
6064 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006065 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006066 push(@Registered, $HPath);
6067 }
6068 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006069 @Registered = sort {sortHeaders($a, $b)} @Registered;
6070 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006071 foreach my $Path (@Registered) {
6072 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
6073 }
6074 }
6075 else {
6076 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
6077 }
6078 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006079
6080 if(defined $Tolerance and $Tolerance=~/4/)
6081 { # 4 - skip headers included by others
6082 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
6083 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006084 if(defined $Header_Includes_R{$LibVersion}{$Path}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006085 delete($Registered_Headers{$LibVersion}{$Path});
6086 }
6087 }
6088 }
6089
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006090 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
6091 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006092 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006093 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006094 if(is_abs($Header) and not -f $Header) {
6095 exitStatus("Access_Error", "can't access file \'$Header\'");
6096 }
6097 $Header = path_format($Header, $OSgroup);
6098 if(my $Header_Path = is_header($Header, 1, $LibVersion))
6099 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006100 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006101 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006102 }
6103 else {
6104 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
6105 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006106 }
6107 }
6108 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
6109 { # set relative paths (for duplicates)
6110 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
6111 { # search for duplicates
6112 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
6113 my $Prefix = get_dirname($FirstPath);
6114 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6115 { # detect a shortest distinguishing prefix
6116 my $NewPrefix = $1;
6117 my %Identity = ();
6118 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6119 {
6120 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6121 $Identity{$Path} = $1;
6122 }
6123 }
6124 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6125 { # all names are differend with current prefix
6126 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6127 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6128 }
6129 last;
6130 }
6131 $Prefix = $NewPrefix; # increase prefix
6132 }
6133 }
6134 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006135
6136 # clean memory
6137 %HeaderName_Paths = ();
6138
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006139 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6140 { # ordering headers according to descriptor
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006141 my $PairName = $Include_Order{$LibVersion}{$HeaderName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006142 my ($Pos, $PairPos) = (-1, -1);
6143 my ($Path, $PairPath) = ();
6144 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6145 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6146 foreach my $Header_Path (@Paths)
6147 {
6148 if(get_filename($Header_Path) eq $PairName)
6149 {
6150 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6151 $PairPath = $Header_Path;
6152 }
6153 if(get_filename($Header_Path) eq $HeaderName)
6154 {
6155 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6156 $Path = $Header_Path;
6157 }
6158 }
6159 if($PairPos!=-1 and $Pos!=-1
6160 and int($PairPos)<int($Pos))
6161 {
6162 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6163 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6164 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6165 }
6166 }
6167 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6168 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6169 }
6170}
6171
6172sub detect_real_includes($$)
6173{
6174 my ($AbsPath, $LibVersion) = @_;
6175 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6176 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6177 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6178 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6179 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006180 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6181
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006182 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6183 return () if(not $Path);
6184 open(PREPROC, $Path);
6185 while(<PREPROC>)
6186 {
6187 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6188 {
6189 my $Include = path_format($1, $OSgroup);
6190 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6191 next;
6192 }
6193 if($Include eq $AbsPath) {
6194 next;
6195 }
6196 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6197 }
6198 }
6199 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006200 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6201}
6202
6203sub detect_header_includes($$)
6204{
6205 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006206 return if(not $LibVersion or not $Path);
6207 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6208 return;
6209 }
6210 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6211
6212 if(not -e $Path) {
6213 return;
6214 }
6215
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006216 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006217 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6218 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006219 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006220 {
6221 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006222 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006223 }
6224 if($RedirectPath ne $Path) {
6225 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6226 }
6227 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006228 else
6229 { # can't find
6230 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6231 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006232 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006233 if(my $Inc = parse_includes($Content, $Path))
6234 {
6235 foreach my $Include (keys(%{$Inc}))
6236 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006237 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006238
6239 if(defined $Tolerance and $Tolerance=~/4/)
6240 {
6241 if(my $HPath = identifyHeader($Include, $LibVersion))
6242 {
6243 $Header_Includes_R{$LibVersion}{$HPath}{$Path} = 1;
6244 }
6245 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006246 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006247 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006248}
6249
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006250sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006251{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006252 my $Path = $_[0];
6253 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006254 if($OStarget eq "symbian")
6255 {
6256 if(get_filename($Dir) eq "libc" and $GlibcHeader{$Name})
6257 { # epoc32/include/libc/{stdio, ...}.h
6258 return 1;
6259 }
6260 }
6261 else
6262 {
6263 if($Dir eq "/usr/include" and $GlibcHeader{$Name})
6264 { # /usr/include/{stdio, ...}.h
6265 return 1;
6266 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006267 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006268 return 0;
6269}
6270
6271sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006272{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006273 my $Dir = $_[0];
6274 my ($OutDir, $Name) = separate_path($Dir);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006275 if($OStarget eq "symbian")
6276 {
6277 if(get_filename($OutDir) eq "libc"
6278 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6279 { # epoc32/include/libc/{sys,bits,asm,asm-*}/*.h
6280 return 1;
6281 }
6282 }
6283 else
6284 { # linux
6285 if($OutDir eq "/usr/include"
6286 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6287 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6288 return 1;
6289 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006290 }
6291 return 0;
6292}
6293
6294sub detect_recursive_includes($$)
6295{
6296 my ($AbsPath, $LibVersion) = @_;
6297 return () if(not $AbsPath);
6298 if(isCyclical(\@RecurInclude, $AbsPath)) {
6299 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6300 }
6301 my ($AbsDir, $Name) = separate_path($AbsPath);
6302 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006303 { # system GLIBC internals
6304 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006305 }
6306 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6307 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6308 }
6309 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006310
6311 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6312 { # skip /usr/include/c++/*/ headers
6313 return () if(not $ExtraInfo);
6314 }
6315
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006316 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006317 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006318 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006319 { # check "real" (non-"model") include paths
6320 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6321 pop(@RecurInclude);
6322 return @Paths;
6323 }
6324 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6325 detect_header_includes($AbsPath, $LibVersion);
6326 }
6327 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6328 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006329 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006330 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006331 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006332 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006333 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006334 if(-f $Candidate) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006335 $HPath = realpath($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006336 }
6337 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006338 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006339 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006340 { # search for the nearest header
6341 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006342 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006343 if(-f $Candidate) {
6344 $HPath = $Candidate;
6345 }
6346 }
6347 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006348 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006349 }
6350 next if(not $HPath);
6351 if($HPath eq $AbsPath) {
6352 next;
6353 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006354
6355 if($Debug)
6356 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006357# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6358# {
6359# print STDERR "$AbsPath -> $HPath\n";
6360# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006361 }
6362
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006363 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6364 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006365 { # only include <...>, skip include "..." prefixes
6366 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6367 }
6368 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6369 {
6370 if($IncPath eq $AbsPath) {
6371 next;
6372 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006373 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6374 if($RIncType==-1)
6375 { # include "..."
6376 $RIncType = $IncType;
6377 }
6378 elsif($RIncType==2)
6379 {
6380 if($IncType!=-1) {
6381 $RIncType = $IncType;
6382 }
6383 }
6384 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006385 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6386 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6387 }
6388 }
6389 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6390 {
6391 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6392 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6393 { # distinguish math.h from glibc and math.h from the tested library
6394 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6395 last;
6396 }
6397 }
6398 }
6399 pop(@RecurInclude);
6400 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6401}
6402
6403sub find_in_framework($$$)
6404{
6405 my ($Header, $Framework, $LibVersion) = @_;
6406 return "" if(not $Header or not $Framework or not $LibVersion);
6407 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6408 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6409 }
6410 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6411 {
6412 if(get_filename($Dependency) eq $Framework
6413 and -f get_dirname($Dependency)."/".$Header) {
6414 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6415 }
6416 }
6417 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6418}
6419
6420sub find_in_defaults($)
6421{
6422 my $Header = $_[0];
6423 return "" if(not $Header);
6424 if(defined $Cache{"find_in_defaults"}{$Header}) {
6425 return $Cache{"find_in_defaults"}{$Header};
6426 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006427 foreach my $Dir (@DefaultIncPaths,
6428 @DefaultGccPaths,
6429 @DefaultCppPaths,
6430 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006431 {
6432 next if(not $Dir);
6433 if(-f $Dir."/".$Header) {
6434 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
6435 }
6436 }
6437 return ($Cache{"find_in_defaults"}{$Header}="");
6438}
6439
6440sub cmp_paths($$)
6441{
6442 my ($Path1, $Path2) = @_;
6443 my @Parts1 = split(/[\/\\]/, $Path1);
6444 my @Parts2 = split(/[\/\\]/, $Path2);
6445 foreach my $Num (0 .. $#Parts1)
6446 {
6447 my $Part1 = $Parts1[$Num];
6448 my $Part2 = $Parts2[$Num];
6449 if($GlibcDir{$Part1}
6450 and not $GlibcDir{$Part2}) {
6451 return 1;
6452 }
6453 elsif($GlibcDir{$Part2}
6454 and not $GlibcDir{$Part1}) {
6455 return -1;
6456 }
6457 elsif($Part1=~/glib/
6458 and $Part2!~/glib/) {
6459 return 1;
6460 }
6461 elsif($Part1!~/glib/
6462 and $Part2=~/glib/) {
6463 return -1;
6464 }
6465 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
6466 return $CmpRes;
6467 }
6468 }
6469 return 0;
6470}
6471
6472sub checkRelevance($)
6473{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006474 my $Path = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006475 return 0 if(not $Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006476
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006477 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006478 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006479 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006480
6481 my $Name = lc(get_filename($Path));
6482 my $Dir = lc(get_dirname($Path));
6483
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006484 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006485
6486 foreach my $Token (split(/[_\d\W]+/, $Name))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006487 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006488 my $Len = length($Token);
6489 next if($Len<=1);
6490 if($Dir=~/(\A|lib|[_\d\W])\Q$Token\E([_\d\W]|lib|\Z)/)
6491 { # include/evolution-data-server-1.4/libebook/e-book.h
6492 return 1;
6493 }
6494 if($Len>=4 and index($Dir, $Token)!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006495 { # include/gupnp-1.0/libgupnp/gupnp-context.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006496 return 1;
6497 }
6498 }
6499 return 0;
6500}
6501
6502sub checkFamily(@)
6503{
6504 my @Paths = @_;
6505 return 1 if($#Paths<=0);
6506 my %Prefix = ();
6507 foreach my $Path (@Paths)
6508 {
6509 if($SystemRoot) {
6510 $Path = cut_path_prefix($Path, $SystemRoot);
6511 }
6512 if(my $Dir = get_dirname($Path))
6513 {
6514 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
6515 $Prefix{$Dir} += 1;
6516 $Prefix{get_dirname($Dir)} += 1;
6517 }
6518 }
6519 foreach (sort keys(%Prefix))
6520 {
6521 if(get_depth($_)>=3
6522 and $Prefix{$_}==$#Paths+1) {
6523 return 1;
6524 }
6525 }
6526 return 0;
6527}
6528
6529sub isAcceptable($$$)
6530{
6531 my ($Header, $Candidate, $LibVersion) = @_;
6532 my $HName = get_filename($Header);
6533 if(get_dirname($Header))
6534 { # with prefix
6535 return 1;
6536 }
6537 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
6538 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
6539 return 1;
6540 }
6541 if(checkRelevance($Candidate))
6542 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
6543 return 1;
6544 }
6545 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
6546 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
6547 # /usr/include/qt4/Qt/qsslconfiguration.h
6548 return 1;
6549 }
6550 if($OStarget eq "symbian")
6551 {
6552 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
6553 return 1;
6554 }
6555 }
6556 return 0;
6557}
6558
6559sub isRelevant($$$)
6560{ # disallow to search for "abstract" headers in too deep directories
6561 my ($Header, $Candidate, $LibVersion) = @_;
6562 my $HName = get_filename($Header);
6563 if($OStarget eq "symbian")
6564 {
6565 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
6566 return 0;
6567 }
6568 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006569 if($OStarget ne "bsd")
6570 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006571 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
6572 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
6573 return 0;
6574 }
6575 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006576 if($OStarget ne "windows")
6577 {
6578 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
6579 { # skip /usr/include/wine/msvcrt
6580 return 0;
6581 }
6582 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006583 if(not get_dirname($Header)
6584 and $Candidate=~/[\/\\]wx[\/\\]/)
6585 { # do NOT search in system /wx/ directory
6586 # for headers without a prefix: sstream.h
6587 return 0;
6588 }
6589 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
6590 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
6591 { # skip ../c++/3.3.3/ if using ../c++/4.5/
6592 return 0;
6593 }
6594 if($Candidate=~/[\/\\]asm-/
6595 and (my $Arch = getArch($LibVersion)) ne "unknown")
6596 { # arch-specific header files
6597 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
6598 {# skip ../asm-arm/ if using x86 architecture
6599 return 0;
6600 }
6601 }
6602 my @Candidates = getSystemHeaders($HName, $LibVersion);
6603 if($#Candidates==1)
6604 { # unique header
6605 return 1;
6606 }
6607 my @SCandidates = getSystemHeaders($Header, $LibVersion);
6608 if($#SCandidates==1)
6609 { # unique name
6610 return 1;
6611 }
6612 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
6613 if(get_depth($Candidate)-$SystemDepth>=5)
6614 { # abstract headers in too deep directories
6615 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
6616 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
6617 return 0;
6618 }
6619 }
6620 if($Header eq "parser.h"
6621 and $Candidate!~/\/libxml2\//)
6622 { # select parser.h from xml2 library
6623 return 0;
6624 }
6625 if(not get_dirname($Header)
6626 and keys(%{$SystemHeaders{$HName}})>=3)
6627 { # many headers with the same name
6628 # like thread.h included without a prefix
6629 if(not checkFamily(@Candidates)) {
6630 return 0;
6631 }
6632 }
6633 return 1;
6634}
6635
6636sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006637{ # cache function
6638 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
6639 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
6640 }
6641 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
6642}
6643
6644sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006645{
6646 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006647 if(-f $Header) {
6648 return $Header;
6649 }
6650 if(is_abs($Header) and not -f $Header)
6651 { # incorrect absolute path
6652 return "";
6653 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006654 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006655 { # too abstract configuration headers
6656 return "";
6657 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006658 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006659 if($OSgroup ne "windows")
6660 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006661 if(defined $WinHeaders{lc($HName)}
6662 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006663 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006664 return "";
6665 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006666 }
6667 if($OSgroup ne "macos")
6668 {
6669 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006670 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006671 return "";
6672 }
6673 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006674
6675 if(defined $ObsoleteHeaders{$HName})
6676 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006677 return "";
6678 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006679 if($OSgroup eq "linux" or $OSgroup eq "bsd")
6680 {
6681 if(defined $AlienHeaders{$HName}
6682 or defined $AlienHeaders{$Header})
6683 { # alien headers from other systems
6684 return "";
6685 }
6686 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006687
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006688 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006689 { # search in default paths
6690 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006691 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006692 }
6693 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006694 if(not keys(%SystemHeaders))
6695 { # register all headers in system include dirs
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006696 detectSystemHeaders();
6697 }
6698 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
6699 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
6700 {
6701 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006702 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006703 }
6704 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006705 # error
6706 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006707}
6708
6709sub getSystemHeaders($$)
6710{
6711 my ($Header, $LibVersion) = @_;
6712 my @Candidates = ();
6713 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
6714 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006715 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006716 next;
6717 }
6718 push(@Candidates, $Candidate);
6719 }
6720 return @Candidates;
6721}
6722
6723sub cut_path_prefix($$)
6724{
6725 my ($Path, $Prefix) = @_;
6726 return $Path if(not $Prefix);
6727 $Prefix=~s/[\/\\]+\Z//;
6728 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
6729 return $Path;
6730}
6731
6732sub is_default_include_dir($)
6733{
6734 my $Dir = $_[0];
6735 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006736 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006737}
6738
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006739sub identifyHeader($$)
6740{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006741 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006742 if(not $Header) {
6743 return "";
6744 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006745 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006746 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
6747 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006748 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006749 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006750}
6751
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006752sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006753{ # search for header by absolute path, relative path or name
6754 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006755 if(-f $Header)
6756 { # it's relative or absolute path
6757 return get_abs_path($Header);
6758 }
6759 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
6760 and my $HeaderDir = find_in_defaults($Header))
6761 { # search for libc headers in the /usr/include
6762 # for non-libc target library before searching
6763 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006764 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006765 }
6766 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
6767 { # search in the target library paths
6768 return $Path;
6769 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006770 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006771 { # search in the internal GCC include paths
6772 return $DefaultGccHeader{$Header};
6773 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006774 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006775 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006776 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006777 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006778 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006779 { # search in the default G++ include paths
6780 return $DefaultCppHeader{$Header};
6781 }
6782 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
6783 { # search everywhere in the system
6784 return $AnyPath;
6785 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006786 elsif($OSgroup eq "macos")
6787 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
6788 if(my $Dir = get_dirname($Header))
6789 {
6790 my $RelPath = "Headers\/".get_filename($Header);
6791 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006792 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006793 }
6794 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006795 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006796 # cannot find anything
6797 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006798}
6799
6800sub getLocation($)
6801{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006802 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6803 {
6804 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006805 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006806 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006807 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006808 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006809}
6810
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006811sub getNameByInfo($)
6812{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006813 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006814 {
6815 if($Info=~/name[ ]*:[ ]*@(\d+) /)
6816 {
6817 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
6818 {
6819 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
6820 { # short unsigned int (may include spaces)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006821 my $Str = $1;
6822 if($CppMode{$Version}
6823 and $Str=~/\Ac99_(.+)\Z/)
6824 {
6825 if($CppKeywords_A{$1}) {
6826 $Str=$1;
6827 }
6828 }
6829 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006830 }
6831 }
6832 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006833 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006834 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006835}
6836
6837sub getTreeStr($)
6838{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006839 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006840 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006841 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
6842 {
6843 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04006844 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006845 and $Str=~/\Ac99_(.+)\Z/)
6846 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006847 if($CppKeywords_A{$1}) {
6848 $Str=$1;
6849 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006850 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006851 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006852 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006853 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006854 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006855}
6856
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006857sub getFuncShortName($)
6858{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006859 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006860 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006861 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006862 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006863 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006864 {
6865 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
6866 {
6867 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
6868 return "operator ".$RName;
6869 }
6870 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006871 }
6872 else
6873 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006874 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
6875 {
6876 if(my $Ind = $Operator_Indication{$1}) {
6877 return "operator".$Ind;
6878 }
6879 elsif(not $UnknownOperator{$1})
6880 {
6881 printMsg("WARNING", "unknown operator $1");
6882 $UnknownOperator{$1} = 1;
6883 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006884 }
6885 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006886 }
6887 else
6888 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006889 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
6890 return getTreeStr($1);
6891 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006892 }
6893 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006894 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006895}
6896
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006897sub getFuncReturn($)
6898{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006899 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6900 {
6901 if($Info=~/type[ ]*:[ ]*@(\d+) /)
6902 {
6903 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
6904 return $1;
6905 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006906 }
6907 }
6908 return "";
6909}
6910
6911sub getFuncOrig($)
6912{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006913 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6914 {
6915 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
6916 return $1;
6917 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006918 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006919 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006920}
6921
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006922sub unmangleArray(@)
6923{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006924 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006925 { # MSVC mangling
6926 my $UndNameCmd = get_CmdPath("undname");
6927 if(not $UndNameCmd) {
6928 exitStatus("Not_Found", "can't find \"undname\"");
6929 }
6930 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006931 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006932 }
6933 else
6934 { # GCC mangling
6935 my $CppFiltCmd = get_CmdPath("c++filt");
6936 if(not $CppFiltCmd) {
6937 exitStatus("Not_Found", "can't find c++filt in PATH");
6938 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006939 if(not defined $CPPFILT_SUPPORT_FILE)
6940 {
6941 my $Info = `$CppFiltCmd -h 2>&1`;
6942 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
6943 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006944 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006945 if($CPPFILT_SUPPORT_FILE)
6946 { # new versions of c++filt can take a file
6947 if($#_>$MAX_CPPFILT_FILE_SIZE)
6948 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
6949 # this is fixed in the oncoming version of Binutils
6950 my @Half = splice(@_, 0, ($#_+1)/2);
6951 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006952 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006953 else
6954 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006955 writeFile("$TMP_DIR/unmangle", join("\n", @_));
6956 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
6957 if($?==139)
6958 { # segmentation fault
6959 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
6960 }
6961 return split(/\n/, $Res);
6962 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006963 }
6964 else
6965 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006966 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
6967 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006968 my @Half = splice(@_, 0, ($#_+1)/2);
6969 return (unmangleArray(@Half), unmangleArray(@_))
6970 }
6971 else
6972 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006973 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006974 my $Res = `$CppFiltCmd $NoStrip $Strings`;
6975 if($?==139)
6976 { # segmentation fault
6977 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
6978 }
6979 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006980 }
6981 }
6982 }
6983}
6984
6985sub get_SignatureNoInfo($$)
6986{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006987 my ($Symbol, $LibVersion) = @_;
6988 if($Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol}) {
6989 return $Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006990 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006991 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006992 my $Signature = $tr_name{$MnglName}?$tr_name{$MnglName}:$MnglName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006993 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006994 { # C++
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04006995 # some standard typedefs
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006996 $Signature=~s/\Qstd::basic_string<char, std::char_traits<char>, std::allocator<char> >\E/std::string/g;
6997 $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;
6998 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04006999 if(not $CheckObjectsOnly or $OSgroup=~/linux|bsd|beos/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007000 { # ELF format marks data as OBJECT
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007001 if($GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007002 $Signature .= " [data]";
7003 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007004 elsif($Symbol!~/\A(_Z|\?)/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007005 $Signature .= " (...)";
7006 }
7007 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007008 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007009 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04007010 my $ShortName = substr($Signature, 0, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007011 $Signature=~s/\A\Q$ShortName\E/$ShortName $ChargeLevel/g;
7012 }
7013 if($SymbolVersion) {
7014 $Signature .= $VersionSpec.$SymbolVersion;
7015 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007016 return ($Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007017}
7018
7019sub get_ChargeLevel($$)
7020{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007021 my ($Symbol, $LibVersion) = @_;
7022 return "" if($Symbol!~/\A(_Z|\?)/);
7023 if(defined $CompleteSignature{$LibVersion}{$Symbol}
7024 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007025 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007026 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007027 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007028 if($Symbol=~/C1E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007029 return "[in-charge]";
7030 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007031 elsif($Symbol=~/C2E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007032 return "[not-in-charge]";
7033 }
7034 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007035 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007036 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007037 if($Symbol=~/D1E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007038 return "[in-charge]";
7039 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007040 elsif($Symbol=~/D2E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007041 return "[not-in-charge]";
7042 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007043 elsif($Symbol=~/D0E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007044 return "[in-charge-deleting]";
7045 }
7046 }
7047 }
7048 else
7049 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007050 if($Symbol=~/C1E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007051 return "[in-charge]";
7052 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007053 elsif($Symbol=~/C2E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007054 return "[not-in-charge]";
7055 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007056 elsif($Symbol=~/D1E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007057 return "[in-charge]";
7058 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007059 elsif($Symbol=~/D2E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007060 return "[not-in-charge]";
7061 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007062 elsif($Symbol=~/D0E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007063 return "[in-charge-deleting]";
7064 }
7065 }
7066 return "";
7067}
7068
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007069sub get_Signature_M($$)
7070{
7071 my ($Symbol, $LibVersion) = @_;
7072 my $Signature_M = $tr_name{$Symbol};
7073 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
7074 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007075 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007076 }
7077 return $Signature_M;
7078}
7079
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007080sub get_Signature($$)
7081{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007082 my ($Symbol, $LibVersion) = @_;
7083 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
7084 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007085 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007086 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
7087 if(isPrivateData($MnglName) or not $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007088 { # non-public global data
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007089 return get_SignatureNoInfo($Symbol, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007090 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007091 my ($Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007092 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
7093 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007094 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007095 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
7096 {
7097 $Signature .= $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::";
7098 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7099 $Signature .= "~";
7100 }
7101 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007102 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007103 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007104 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007105 }
7106 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007107 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007108 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007109 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7110 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007111 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007112 else
7113 {
7114 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007115 }
7116 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007117 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007118 {
7119 next if($Pos eq "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007120 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007121 next if(not $ParamTypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007122 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007123 if(not $ParamTypeName) {
7124 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7125 }
7126 foreach my $Typedef (keys(%ChangedTypedef))
7127 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007128 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7129 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7130 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007131 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007132 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007133 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
7134 }
7135 else {
7136 push(@ParamArray, $ParamTypeName);
7137 }
7138 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007139 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7140 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007141 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007142 }
7143 else
7144 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007145 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007146 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007147 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007148 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007149 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007150 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7151 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007152 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007153 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007154 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7155 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007156 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007157 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007158 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7159 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007160 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007161 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007162 }
7163 }
7164 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007165 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007166 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007167 }
7168 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007169 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007170 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007171 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007172}
7173
7174sub create_member_decl($$)
7175{
7176 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007177 if($TName=~/\([\*]+\)/)
7178 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007179 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7180 return $TName;
7181 }
7182 else
7183 {
7184 my @ArraySizes = ();
7185 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7186 push(@ArraySizes, $1);
7187 }
7188 return $TName." ".$Member.join("", @ArraySizes);
7189 }
7190}
7191
7192sub getFuncType($)
7193{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007194 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7195 {
7196 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7197 {
7198 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7199 {
7200 if($Type eq "method_type") {
7201 return "Method";
7202 }
7203 elsif($Type eq "function_type") {
7204 return "Function";
7205 }
7206 else {
7207 return "Other";
7208 }
7209 }
7210 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007211 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007212 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007213}
7214
7215sub getFuncTypeId($)
7216{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007217 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7218 {
7219 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7220 return $1;
7221 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007222 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007223 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007224}
7225
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007226sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007227{ # "._N" or "$_N" in older GCC versions
7228 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007229}
7230
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007231sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007232{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007233 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7234 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007235 }
7236
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007237 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007238
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007239 if($_[1] ne "S")
7240 {
7241 $N=~s/\A[ ]+//g;
7242 $N=~s/[ ]+\Z//g;
7243 $N=~s/[ ]{2,}/ /g;
7244 }
7245
7246 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007247
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007248 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007249
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007250 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7251 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007252
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007253 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007254
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007255 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007256
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007257 if($_[1] eq "S")
7258 {
7259 if(index($N, "operator")!=-1) {
7260 $N=~s/\b(operator[ ]*)> >/$1>>/;
7261 }
7262 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007263
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007264 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007265}
7266
7267sub get_HeaderDeps($$)
7268{
7269 my ($AbsPath, $LibVersion) = @_;
7270 return () if(not $AbsPath or not $LibVersion);
7271 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7272 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7273 }
7274 my %IncDir = ();
7275 detect_recursive_includes($AbsPath, $LibVersion);
7276 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7277 {
7278 next if(not $HeaderPath);
7279 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7280 my $Dir = get_dirname($HeaderPath);
7281 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7282 {
7283 my $Dep = $Dir;
7284 if($Prefix)
7285 {
7286 if($OSgroup eq "windows")
7287 { # case insensitive seach on windows
7288 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7289 next;
7290 }
7291 }
7292 elsif($OSgroup eq "macos")
7293 { # seach in frameworks
7294 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7295 {
7296 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7297 {# frameworks
7298 my ($HFramework, $HName) = ($1, $2);
7299 $Dep = $HFramework;
7300 }
7301 else
7302 {# mismatch
7303 next;
7304 }
7305 }
7306 }
7307 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7308 { # Linux, FreeBSD
7309 next;
7310 }
7311 }
7312 if(not $Dep)
7313 { # nothing to include
7314 next;
7315 }
7316 if(is_default_include_dir($Dep))
7317 { # included by the compiler
7318 next;
7319 }
7320 if(get_depth($Dep)==1)
7321 { # too short
7322 next;
7323 }
7324 if(isLibcDir($Dep))
7325 { # do NOT include /usr/include/{sys,bits}
7326 next;
7327 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007328 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007329 }
7330 }
7331 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7332 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7333}
7334
7335sub sortIncPaths($$)
7336{
7337 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007338 if(not $ArrRef or $#{$ArrRef}<0) {
7339 return $ArrRef;
7340 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007341 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7342 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007343 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007344 return $ArrRef;
7345}
7346
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007347sub sortDeps($$$)
7348{
7349 if($Header_Dependency{$_[2]}{$_[0]}
7350 and not $Header_Dependency{$_[2]}{$_[1]}) {
7351 return 1;
7352 }
7353 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7354 and $Header_Dependency{$_[2]}{$_[1]}) {
7355 return -1;
7356 }
7357 return 0;
7358}
7359
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007360sub join_P($$)
7361{
7362 my $S = "/";
7363 if($OSgroup eq "windows") {
7364 $S = "\\";
7365 }
7366 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007367}
7368
7369sub get_namespace_additions($)
7370{
7371 my $NameSpaces = $_[0];
7372 my ($Additions, $AddNameSpaceId) = ("", 1);
7373 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7374 {
7375 next if($SkipNameSpaces{$Version}{$NS});
7376 next if(not $NS or $NameSpaces->{$NS}==-1);
7377 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7378 next if($NS=~/\A__/i);
7379 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007380 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007381 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7382 my @NS_Parts = split(/::/, $NS);
7383 next if($#NS_Parts==-1);
7384 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7385 foreach my $NS_Part (@NS_Parts)
7386 {
7387 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7388 $TypeDecl_Suffix .= "}";
7389 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007390 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007391 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7392 $Additions.=" $TypeDecl\n $FuncDecl\n";
7393 $AddNameSpaceId+=1;
7394 }
7395 return $Additions;
7396}
7397
7398sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007399{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007400 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007401 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007402 if($Fmt eq "windows")
7403 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007404 $Path=~s/\//\\/g;
7405 $Path=lc($Path);
7406 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007407 else
7408 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007409 $Path=~s/\\/\//g;
7410 }
7411 return $Path;
7412}
7413
7414sub inc_opt($$)
7415{
7416 my ($Path, $Style) = @_;
7417 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007418 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007419 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007420 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007421 return "-I\"".path_format($Path, "unix")."\"";
7422 }
7423 elsif($OSgroup eq "macos"
7424 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007425 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007426 return "-F".esc(get_dirname($Path));
7427 }
7428 else {
7429 return "-I".esc($Path);
7430 }
7431 }
7432 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007433 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007434 }
7435 return "";
7436}
7437
7438sub platformSpecs($)
7439{
7440 my $LibVersion = $_[0];
7441 my $Arch = getArch($LibVersion);
7442 if($OStarget eq "symbian")
7443 { # options for GCCE compiler
7444 my %Symbian_Opts = map {$_=>1} (
7445 "-D__GCCE__",
7446 "-DUNICODE",
7447 "-fexceptions",
7448 "-D__SYMBIAN32__",
7449 "-D__MARM_INTERWORK__",
7450 "-D_UNICODE",
7451 "-D__S60_50__",
7452 "-D__S60_3X__",
7453 "-D__SERIES60_3X__",
7454 "-D__EPOC32__",
7455 "-D__MARM__",
7456 "-D__EABI__",
7457 "-D__MARM_ARMV5__",
7458 "-D__SUPPORT_CPP_EXCEPTIONS__",
7459 "-march=armv5t",
7460 "-mapcs",
7461 "-mthumb-interwork",
7462 "-DEKA2",
7463 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
7464 );
7465 return join(" ", keys(%Symbian_Opts));
7466 }
7467 elsif($OSgroup eq "windows"
7468 and get_dumpmachine($GCC_PATH)=~/mingw/i)
7469 { # add options to MinGW compiler
7470 # to simulate the MSVC compiler
7471 my %MinGW_Opts = map {$_=>1} (
7472 "-D_WIN32",
7473 "-D_STDCALL_SUPPORTED",
7474 "-D__int64=\"long long\"",
7475 "-D__int32=int",
7476 "-D__int16=short",
7477 "-D__int8=char",
7478 "-D__possibly_notnullterminated=\" \"",
7479 "-D__nullterminated=\" \"",
7480 "-D__nullnullterminated=\" \"",
7481 "-D__w64=\" \"",
7482 "-D__ptr32=\" \"",
7483 "-D__ptr64=\" \"",
7484 "-D__forceinline=inline",
7485 "-D__inline=inline",
7486 "-D__uuidof(x)=IID()",
7487 "-D__try=",
7488 "-D__except(x)=",
7489 "-D__declspec(x)=__attribute__((x))",
7490 "-D__pragma(x)=",
7491 "-D_inline=inline",
7492 "-D__forceinline=__inline",
7493 "-D__stdcall=__attribute__((__stdcall__))",
7494 "-D__cdecl=__attribute__((__cdecl__))",
7495 "-D__fastcall=__attribute__((__fastcall__))",
7496 "-D__thiscall=__attribute__((__thiscall__))",
7497 "-D_stdcall=__attribute__((__stdcall__))",
7498 "-D_cdecl=__attribute__((__cdecl__))",
7499 "-D_fastcall=__attribute__((__fastcall__))",
7500 "-D_thiscall=__attribute__((__thiscall__))",
7501 "-DSHSTDAPI_(x)=x",
7502 "-D_MSC_EXTENSIONS",
7503 "-DSECURITY_WIN32",
7504 "-D_MSC_VER=1500",
7505 "-D_USE_DECLSPECS_FOR_SAL",
7506 "-D__noop=\" \"",
7507 "-DDECLSPEC_DEPRECATED=\" \"",
7508 "-D__builtin_alignof(x)=__alignof__(x)",
7509 "-DSORTPP_PASS");
7510 if($Arch eq "x86") {
7511 $MinGW_Opts{"-D_M_IX86=300"}=1;
7512 }
7513 elsif($Arch eq "x86_64") {
7514 $MinGW_Opts{"-D_M_AMD64=300"}=1;
7515 }
7516 elsif($Arch eq "ia64") {
7517 $MinGW_Opts{"-D_M_IA64=300"}=1;
7518 }
7519 return join(" ", keys(%MinGW_Opts));
7520 }
7521 return "";
7522}
7523
7524my %C_Structure = map {$_=>1} (
7525# FIXME: Can't separate union and struct data types before dumping,
7526# so it sometimes cause compilation errors for unknown reason
7527# when trying to declare TYPE* tmp_add_class_N
7528# This is a list of such structures + list of other C structures
7529 "sigval",
7530 "sigevent",
7531 "sigaction",
7532 "sigvec",
7533 "sigstack",
7534 "timeval",
7535 "timezone",
7536 "rusage",
7537 "rlimit",
7538 "wait",
7539 "flock",
7540 "stat",
7541 "_stat",
7542 "stat32",
7543 "_stat32",
7544 "stat64",
7545 "_stat64",
7546 "_stati64",
7547 "if_nameindex",
7548 "usb_device",
7549 "sigaltstack",
7550 "sysinfo",
7551 "timeLocale",
7552 "tcp_debug",
7553 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007554 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007555 "timespec",
7556 "random_data",
7557 "drand48_data",
7558 "_IO_marker",
7559 "_IO_FILE",
7560 "lconv",
7561 "sched_param",
7562 "tm",
7563 "itimerspec",
7564 "_pthread_cleanup_buffer",
7565 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007566 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007567 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007568 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007569 "sigcontext",
7570 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007571 # Mac
7572 "_timex",
7573 "_class_t",
7574 "_category_t",
7575 "_class_ro_t",
7576 "_protocol_t",
7577 "_message_ref_t",
7578 "_super_message_ref_t",
7579 "_ivar_t",
7580 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007581);
7582
7583sub getCompileCmd($$$)
7584{
7585 my ($Path, $Opt, $Inc) = @_;
7586 my $GccCall = $GCC_PATH;
7587 if($Opt) {
7588 $GccCall .= " ".$Opt;
7589 }
7590 $GccCall .= " -x ";
7591 if($OSgroup eq "macos") {
7592 $GccCall .= "objective-";
7593 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007594 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007595 { # compile as "C++" header
7596 # to obtain complete dump using GCC 4.0
7597 $GccCall .= "c++-header";
7598 }
7599 else
7600 { # compile as "C++" source
7601 # GCC 3.3 cannot compile headers
7602 $GccCall .= "c++";
7603 }
7604 if(my $Opts = platformSpecs($Version))
7605 {# platform-specific options
7606 $GccCall .= " ".$Opts;
7607 }
7608 # allow extra qualifications
7609 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007610 $GccCall .= " -fpermissive";
7611 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007612 if($NoStdInc)
7613 {
7614 $GccCall .= " -nostdinc";
7615 $GccCall .= " -nostdinc++";
7616 }
7617 if($CompilerOptions{$Version})
7618 { # user-defined options
7619 $GccCall .= " ".$CompilerOptions{$Version};
7620 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007621 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007622 if($Inc)
7623 { # include paths
7624 $GccCall .= " ".$Inc;
7625 }
7626 return $GccCall;
7627}
7628
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007629sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007630{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007631 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007632 my %HeaderElems = (
7633 # Types
7634 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007635 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007636 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
7637 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007638 "time.h" => ["time_t"],
7639 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007640 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
7641 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007642 "stdbool.h" => ["_Bool"],
7643 "rpc/xdr.h" => ["bool_t"],
7644 "in_systm.h" => ["n_long", "n_short"],
7645 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04007646 "arpa/inet.h" => ["fw_src", "ip_src"],
7647 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007648 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007649 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007650 );
7651 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007652 foreach (keys(%HeaderElems))
7653 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007654 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007655 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007656 }
7657 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007658 my %Types = ();
7659 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
7660 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007661 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007662 }
7663 if(keys(%Types))
7664 {
7665 my %AddHeaders = ();
7666 foreach my $Type (keys(%Types))
7667 {
7668 if(my $Header = $AutoPreamble{$Type})
7669 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007670 if(my $Path = identifyHeader($Header, $LibVersion))
7671 {
7672 if(skipHeader($Path, $LibVersion)) {
7673 next;
7674 }
7675 $Path = path_format($Path, $OSgroup);
7676 $AddHeaders{$Path}{"Type"} = $Type;
7677 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007678 }
7679 }
7680 }
7681 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007682 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007683 }
7684 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007685 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007686}
7687
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007688sub checkCTags($)
7689{
7690 my $Path = $_[0];
7691 if(not $Path) {
7692 return;
7693 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007694 my $CTags = undef;
7695
7696 if($OSgroup eq "bsd")
7697 { # use ectags on BSD
7698 $CTags = get_CmdPath("ectags");
7699 if(not $CTags) {
7700 printMsg("WARNING", "can't find \'ectags\' program");
7701 }
7702 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007703 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007704 $CTags = get_CmdPath("ctags");
7705 }
7706 if(not $CTags)
7707 {
7708 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007709 return;
7710 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04007711
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007712 if($OSgroup ne "linux")
7713 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04007714 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
7715 if($Info!~/exuberant/i)
7716 {
7717 printMsg("WARNING", "incompatible version of \'ctags\' program");
7718 return;
7719 }
7720 }
7721
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007722 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04007723 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007724 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007725 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007726 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007727 open(CTAGS, "<", $Out);
7728 while(my $Line = <CTAGS>)
7729 {
7730 chomp($Line);
7731 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007732 if(defined $Intrinsic_Keywords{$Name})
7733 { # noise
7734 next;
7735 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007736 if($Type eq "n")
7737 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007738 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007739 next;
7740 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007741 if(index($Scpe, "struct:")==0) {
7742 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007743 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007744 if(index($Scpe, "namespace:")==0)
7745 {
7746 if($Scpe=~s/\Anamespace://) {
7747 $Name = $Scpe."::".$Name;
7748 }
7749 }
7750 $TUnit_NameSpaces{$Version}{$Name} = 1;
7751 }
7752 elsif($Type eq "p")
7753 {
7754 if(not $Scpe or index($Scpe, "namespace:")==0) {
7755 $TUnit_Funcs{$Version}{$Name} = 1;
7756 }
7757 }
7758 elsif($Type eq "x")
7759 {
7760 if(not $Scpe or index($Scpe, "namespace:")==0) {
7761 $TUnit_Vars{$Version}{$Name} = 1;
7762 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007763 }
7764 }
7765 close(CTAGS);
7766}
7767
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007768sub preChange($$)
7769{
7770 my ($HeaderPath, $IncStr) = @_;
7771
7772 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
7773 my $Content = undef;
7774
7775 if($OStarget eq "windows"
7776 and get_dumpmachine($GCC_PATH)=~/mingw/i
7777 and $MinGWMode{$Version}!=-1)
7778 { # modify headers to compile by MinGW
7779 if(not $Content)
7780 { # preprocessing
7781 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
7782 }
7783 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
7784 { # __asm { ... }
7785 $MinGWMode{$Version}=1;
7786 }
7787 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
7788 { # comments after preprocessing
7789 $MinGWMode{$Version}=1;
7790 }
7791 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
7792 { # 0xffui8
7793 $MinGWMode{$Version}=1;
7794 }
7795
7796 if($MinGWMode{$Version}) {
7797 printMsg("INFO", "Using MinGW compatibility mode");
7798 }
7799 }
7800
7801 if(($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
7802 and $CppMode{$Version}!=-1 and not $CppCompat and not $CPP_HEADERS)
7803 { # rename C++ keywords in C code
7804 # disable this code by -cpp-compatible option
7805 if(not $Content)
7806 { # preprocessing
7807 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
7808 }
7809 my $RegExp_C = join("|", keys(%CppKeywords_C));
7810 my $RegExp_F = join("|", keys(%CppKeywords_F));
7811 my $RegExp_O = join("|", keys(%CppKeywords_O));
7812
7813 my $Detected = undef;
7814
7815 while($Content=~s/(\A|\n[^\#\/\n][^\n]*?|\n)(\*\s*|\s+|\@|\,|\()($RegExp_C|$RegExp_F)(\s*(\,|\)|\;|\-\>|\.|\:\s*\d))/$1$2c99_$3$4/g)
7816 { # MATCH:
7817 # int foo(int new, int class, int (*new)(int));
7818 # unsigned private: 8;
7819 # DO NOT MATCH:
7820 # #pragma GCC visibility push(default)
7821 $CppMode{$Version} = 1;
7822 $Detected = "$1$2$3$4" if(not defined $Detected);
7823 }
7824 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
7825 { # MATCH:
7826 # int delete(...);
7827 # int explicit(...);
7828 # DO NOT MATCH:
7829 # void operator delete(...)
7830 $CppMode{$Version} = 1;
7831 $Detected = "$1$2$3" if(not defined $Detected);
7832 }
7833 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
7834 { # MATCH:
7835 # int bool;
7836 # DO NOT MATCH:
7837 # bool X;
7838 # return *this;
7839 # throw;
7840 $CppMode{$Version} = 1;
7841 $Detected = "$1$2$3" if(not defined $Detected);
7842 }
7843 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
7844 { # MATCH:
7845 # int operator(...);
7846 # DO NOT MATCH:
7847 # int operator()(...);
7848 $CppMode{$Version} = 1;
7849 $Detected = "$1$2$3" if(not defined $Detected);
7850 }
7851 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
7852 { # MATCH:
7853 # int foo(int operator);
7854 # int foo(int operator, int other);
7855 # DO NOT MATCH:
7856 # int operator,(...);
7857 $CppMode{$Version} = 1;
7858 $Detected = "$1$2$3" if(not defined $Detected);
7859 }
7860 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
7861 { # MATCH:
7862 # int foo(gboolean *bool);
7863 # DO NOT MATCH:
7864 # void setTabEnabled(int index, bool);
7865 $CppMode{$Version} = 1;
7866 $Detected = "$1$2$3" if(not defined $Detected);
7867 }
7868 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
7869 { # MATCH:
7870 # int foo(int* this);
7871 # int bar(int this);
7872 # int baz(int throw);
7873 # DO NOT MATCH:
7874 # foo(X, this);
7875 $CppMode{$Version} = 1;
7876 $Detected = "$1$2$3$4" if(not defined $Detected);
7877 }
7878 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
7879 { # MATCH:
7880 # struct template {...};
7881 # extern template foo(...);
7882 $CppMode{$Version} = 1;
7883 $Detected = "$1$2" if(not defined $Detected);
7884 }
7885
7886 if($CppMode{$Version} == 1)
7887 {
7888 if($Debug)
7889 {
7890 $Detected=~s/\A\s+//g;
7891 printMsg("INFO", "Detected code: \"$Detected\"");
7892 }
7893 }
7894
7895 # remove typedef enum NAME NAME;
7896 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
7897 my $N = 0;
7898 while($N<=$#FwdTypedefs-1)
7899 {
7900 my $S = $FwdTypedefs[$N];
7901 if($S eq $FwdTypedefs[$N+1])
7902 {
7903 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007904 $CppMode{$Version} = 1;
7905
7906 if($Debug) {
7907 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
7908 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007909 }
7910 $N+=2;
7911 }
7912
7913 if($CppMode{$Version}==1) {
7914 printMsg("INFO", "Using C++ compatibility mode");
7915 }
7916 }
7917
7918 if($CppMode{$Version}==1
7919 or $MinGWMode{$Version}==1)
7920 {
7921 my $IPath = $TMP_DIR."/dump$Version.i";
7922 writeFile($IPath, $Content);
7923 return $IPath;
7924 }
7925
7926 return undef;
7927}
7928
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007929sub getDump()
7930{
7931 if(not $GCC_PATH) {
7932 exitStatus("Error", "internal error - GCC path is not set");
7933 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007934
7935 my @Headers = keys(%{$Registered_Headers{$Version}});
7936 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
7937
7938 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
7939
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007940 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007941 my $HeaderPath = $TmpHeaderPath;
7942
7943 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007944 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007945 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
7946 {
7947 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007948 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007949 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007950 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007951 foreach my $HPath (@{$Include_Preamble{$Version}}) {
7952 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007953 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007954 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007955 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007956 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
7957 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
7958 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007959 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007960 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007961
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007962 if($ExtraInfo)
7963 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007964 if($IncludeString) {
7965 writeFile($ExtraInfo."/include-string", $IncludeString);
7966 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04007967 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
7968 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007969
7970 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
7971 {
7972 my $REDIR = "";
7973 foreach my $P1 (sort @Redirects) {
7974 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
7975 }
7976 writeFile($ExtraInfo."/include-redirect", $REDIR);
7977 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007978 }
7979
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007980 if(not keys(%{$TargetHeaders{$Version}}))
7981 { # Target headers
7982 addTargetHeaders($Version);
7983 }
7984
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007985 # clean memory
7986 %RecursiveIncludes = ();
7987 %Header_Include_Prefix = ();
7988 %Header_Includes = ();
7989
7990 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007991 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007992 delete($Cache{"detect_header_includes"});
7993 delete($Cache{"selectSystemHeader"});
7994
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007995 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007996 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
7997 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007998
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007999 if($ExtraInfo)
8000 { # extra information for other tools
8001 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8002 }
8003
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008004 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008005 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008006 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008007
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008008 if($COMMON_LANGUAGE{$Version} eq "C++") {
8009 checkCTags($Pre);
8010 }
8011
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008012 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8013 { # try to correct the preprocessor output
8014 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008015 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008016
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008017 if($COMMON_LANGUAGE{$Version} eq "C++")
8018 { # add classes and namespaces to the dump
8019 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008020 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008021 or $MinGWMode{$Version}==1) {
8022 $CHdump .= " -fpreprocessed";
8023 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008024 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008025 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008026 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008027 chdir($ORIG_DIR);
8028 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8029 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008030 my $Content = readFile($ClassDump);
8031 foreach my $ClassInfo (split(/\n\n/, $Content))
8032 {
8033 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8034 {
8035 my $CName = $1;
8036 next if($CName=~/\A(__|_objc_|_opaque_)/);
8037 $TUnit_NameSpaces{$Version}{$CName} = -1;
8038 if($CName=~/\A[\w:]+\Z/)
8039 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008040 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008041 }
8042 if($CName=~/(\w[\w:]*)::/)
8043 { # namespaces
8044 my $NS = $1;
8045 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8046 $TUnit_NameSpaces{$Version}{$NS} = 1;
8047 }
8048 }
8049 }
8050 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8051 { # read v-tables (advanced approach)
8052 my ($CName, $VTable) = ($1, $2);
8053 $ClassVTable_Content{$Version}{$CName} = $VTable;
8054 }
8055 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008056 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8057 { # add user-defined namespaces
8058 $TUnit_NameSpaces{$Version}{$NS} = 1;
8059 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008060 if($Debug)
8061 { # debug mode
8062 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008063 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008064 }
8065 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008066 }
8067
8068 # add namespaces and classes
8069 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8070 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008071 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008072 }
8073 # some GCC versions don't include class methods to the TU dump by default
8074 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008075 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008076 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8077 {
8078 next if($C_Structure{$CName});
8079 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008080 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008081 if(not $Force and $GCC_44
8082 and $OSgroup eq "linux")
8083 { # optimization for linux with GCC >= 4.4
8084 # disable this code by -force option
8085 if(index($CName, "::")!=-1)
8086 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008087 next;
8088 }
8089 }
8090 else
8091 {
8092 if($CName=~/\A(.+)::[^:]+\Z/
8093 and $TUnit_Classes{$Version}{$1})
8094 { # classes inside other classes
8095 next;
8096 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008097 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008098 if(defined $TUnit_Funcs{$Version}{$CName})
8099 { # the same name for a function and type
8100 next;
8101 }
8102 if(defined $TUnit_Vars{$Version}{$CName})
8103 { # the same name for a variable and type
8104 next;
8105 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008106 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8107 }
8108 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008109 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008110 }
8111 }
8112 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8113 # create TU dump
8114 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008115 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008116 or $MinGWMode{$Version}==1) {
8117 $TUdump .= " -fpreprocessed";
8118 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008119 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008120 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8121 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008122 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008123 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008124 if($?)
8125 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008126 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008127 { # try to recompile
8128 # FIXME: handle other errors and try to recompile
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008129 if($CppMode{$Version}==1
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008130 and index($Errors, "c99_")!=-1)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008131 { # disable c99 mode and try again
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008132 $CppMode{$Version}=-1;
8133 printMsg("INFO", "Disabling C++ compatibility mode");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008134 resetLogging($Version);
8135 $TMP_DIR = tempdir(CLEANUP=>1);
8136 return getDump();
8137 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008138 elsif($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008139 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008140 { # add auto preamble headers and try again
8141 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008142 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008143 foreach my $Num (0 .. $#Headers)
8144 {
8145 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008146 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8147 {
8148 push_U($Include_Preamble{$Version}, $Path);
8149 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008150 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008151 }
8152 resetLogging($Version);
8153 $TMP_DIR = tempdir(CLEANUP=>1);
8154 return getDump();
8155 }
8156 elsif($Cpp0xMode{$Version}!=-1
8157 and ($Errors=~/\Q-std=c++0x\E/
8158 or $Errors=~/is not a class or namespace/))
8159 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008160 if(check_gcc($GCC_PATH, "4.6"))
8161 {
8162 $Cpp0xMode{$Version}=-1;
8163 printMsg("INFO", "Enabling c++0x mode");
8164 resetLogging($Version);
8165 $TMP_DIR = tempdir(CLEANUP=>1);
8166 $CompilerOptions{$Version} .= " -std=c++0x";
8167 return getDump();
8168 }
8169 else {
8170 printMsg("WARNING", "Probably c++0x construction detected");
8171 }
8172
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008173 }
8174 elsif($MinGWMode{$Version}==1)
8175 { # disable MinGW mode and try again
8176 $MinGWMode{$Version}=-1;
8177 resetLogging($Version);
8178 $TMP_DIR = tempdir(CLEANUP=>1);
8179 return getDump();
8180 }
8181 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008182 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008183 else {
8184 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008185 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008186 printMsg("ERROR", "some errors occurred when compiling headers");
8187 printErrorLog($Version);
8188 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008189 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008190 }
8191 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008192 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008193 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008194
8195 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8196 return $TUs[0];
8197 }
8198 else
8199 {
8200 my $Msg = "can't compile header(s)";
8201 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8202 $Msg .= "\nDid you install G++?";
8203 }
8204 exitStatus("Cannot_Compile", $Msg);
8205 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008206}
8207
8208sub cmd_file($)
8209{
8210 my $Path = $_[0];
8211 return "" if(not $Path or not -e $Path);
8212 if(my $CmdPath = get_CmdPath("file")) {
8213 return `$CmdPath -b \"$Path\"`;
8214 }
8215 return "";
8216}
8217
8218sub getIncString($$)
8219{
8220 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008221 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008222 my $String = "";
8223 foreach (@{$ArrRef}) {
8224 $String .= " ".inc_opt($_, $Style);
8225 }
8226 return $String;
8227}
8228
8229sub getIncPaths(@)
8230{
8231 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008232 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008233 if($INC_PATH_AUTODETECT{$Version})
8234 { # auto-detecting dependencies
8235 my %Includes = ();
8236 foreach my $HPath (@HeaderPaths)
8237 {
8238 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8239 {
8240 if($Skip_Include_Paths{$Version}{$Dir}) {
8241 next;
8242 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008243 if($SystemRoot)
8244 {
8245 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8246 next;
8247 }
8248 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008249 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008250 }
8251 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008252 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008253 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008254 }
8255 }
8256 else
8257 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008258 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008259 }
8260 return \@IncPaths;
8261}
8262
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008263sub push_U($@)
8264{ # push unique
8265 if(my $Array = shift @_)
8266 {
8267 if(@_)
8268 {
8269 my %Exist = map {$_=>1} @{$Array};
8270 foreach my $Elem (@_)
8271 {
8272 if(not defined $Exist{$Elem})
8273 {
8274 push(@{$Array}, $Elem);
8275 $Exist{$Elem} = 1;
8276 }
8277 }
8278 }
8279 }
8280}
8281
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008282sub callPreprocessor($$$)
8283{
8284 my ($Path, $Inc, $LibVersion) = @_;
8285 return "" if(not $Path or not -f $Path);
8286 my $IncludeString=$Inc;
8287 if(not $Inc) {
8288 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8289 }
8290 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008291 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008292 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008293 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008294}
8295
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008296sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008297{ # native "find" is much faster than File::Find (~6x)
8298 # also the File::Find doesn't support --maxdepth N option
8299 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008300 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008301 return () if(not $Path or not -e $Path);
8302 if($OSgroup eq "windows")
8303 {
8304 my $DirCmd = get_CmdPath("dir");
8305 if(not $DirCmd) {
8306 exitStatus("Not_Found", "can't find \"dir\" command");
8307 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008308 $Path = get_abs_path($Path);
8309 $Path = path_format($Path, $OSgroup);
8310 my $Cmd = $DirCmd." \"$Path\" /B /O";
8311 if($MaxDepth!=1) {
8312 $Cmd .= " /S";
8313 }
8314 if($Type eq "d") {
8315 $Cmd .= " /AD";
8316 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008317 elsif($Type eq "f") {
8318 $Cmd .= " /A-D";
8319 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008320 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008321 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008322 {
8323 if(not $UseRegex)
8324 { # FIXME: how to search file names in MS shell?
8325 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008326 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008327 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008328 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008329 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008330 }
8331 my @AbsPaths = ();
8332 foreach my $File (@Files)
8333 {
8334 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008335 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008336 }
8337 if($Type eq "f" and not -f $File)
8338 { # skip dirs
8339 next;
8340 }
8341 push(@AbsPaths, path_format($File, $OSgroup));
8342 }
8343 if($Type eq "d") {
8344 push(@AbsPaths, $Path);
8345 }
8346 return @AbsPaths;
8347 }
8348 else
8349 {
8350 my $FindCmd = get_CmdPath("find");
8351 if(not $FindCmd) {
8352 exitStatus("Not_Found", "can't find a \"find\" command");
8353 }
8354 $Path = get_abs_path($Path);
8355 if(-d $Path and -l $Path
8356 and $Path!~/\/\Z/)
8357 { # for directories that are symlinks
8358 $Path.="/";
8359 }
8360 my $Cmd = $FindCmd." \"$Path\"";
8361 if($MaxDepth) {
8362 $Cmd .= " -maxdepth $MaxDepth";
8363 }
8364 if($Type) {
8365 $Cmd .= " -type $Type";
8366 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008367 if($Name and not $UseRegex)
8368 { # wildcards
8369 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008370 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008371 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008372 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008373 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8374 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008375 my @Files = split(/\n/, $Res);
8376 if($Name and $UseRegex)
8377 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008378 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008379 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008380 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008381 }
8382}
8383
8384sub unpackDump($)
8385{
8386 my $Path = $_[0];
8387 return "" if(not $Path or not -e $Path);
8388 $Path = get_abs_path($Path);
8389 $Path = path_format($Path, $OSgroup);
8390 my ($Dir, $FileName) = separate_path($Path);
8391 my $UnpackDir = $TMP_DIR."/unpack";
8392 rmtree($UnpackDir);
8393 mkpath($UnpackDir);
8394 if($FileName=~s/\Q.zip\E\Z//g)
8395 { # *.zip
8396 my $UnzipCmd = get_CmdPath("unzip");
8397 if(not $UnzipCmd) {
8398 exitStatus("Not_Found", "can't find \"unzip\" command");
8399 }
8400 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008401 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008402 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008403 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008404 }
8405 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008406 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008407 if(not @Contents) {
8408 exitStatus("Error", "can't extract \'$Path\'");
8409 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008410 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008411 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008412 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008413 { # *.tar.gz
8414 if($OSgroup eq "windows")
8415 { # -xvzf option is not implemented in tar.exe (2003)
8416 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8417 my $TarCmd = get_CmdPath("tar");
8418 if(not $TarCmd) {
8419 exitStatus("Not_Found", "can't find \"tar\" command");
8420 }
8421 my $GzipCmd = get_CmdPath("gzip");
8422 if(not $GzipCmd) {
8423 exitStatus("Not_Found", "can't find \"gzip\" command");
8424 }
8425 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008426 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008427 if($?) {
8428 exitStatus("Error", "can't extract \'$Path\'");
8429 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008430 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008431 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008432 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008433 }
8434 chdir($ORIG_DIR);
8435 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008436 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008437 if(not @Contents) {
8438 exitStatus("Error", "can't extract \'$Path\'");
8439 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008440 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008441 }
8442 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008443 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008444 my $TarCmd = get_CmdPath("tar");
8445 if(not $TarCmd) {
8446 exitStatus("Not_Found", "can't find \"tar\" command");
8447 }
8448 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008449 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008450 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008451 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008452 }
8453 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008454 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008455 if(not @Contents) {
8456 exitStatus("Error", "can't extract \'$Path\'");
8457 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008458 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008459 }
8460 }
8461}
8462
8463sub createArchive($$)
8464{
8465 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008466 if(not $To) {
8467 $To = ".";
8468 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008469 if(not $Path or not -e $Path
8470 or not -d $To) {
8471 return "";
8472 }
8473 my ($From, $Name) = separate_path($Path);
8474 if($OSgroup eq "windows")
8475 { # *.zip
8476 my $ZipCmd = get_CmdPath("zip");
8477 if(not $ZipCmd) {
8478 exitStatus("Not_Found", "can't find \"zip\"");
8479 }
8480 my $Pkg = $To."/".$Name.".zip";
8481 unlink($Pkg);
8482 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008483 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008484 if($?)
8485 { # cannot allocate memory (or other problems with "zip")
8486 unlink($Path);
8487 exitStatus("Error", "can't pack the ABI dump: ".$!);
8488 }
8489 chdir($ORIG_DIR);
8490 unlink($Path);
8491 return $Pkg;
8492 }
8493 else
8494 { # *.tar.gz
8495 my $TarCmd = get_CmdPath("tar");
8496 if(not $TarCmd) {
8497 exitStatus("Not_Found", "can't find \"tar\"");
8498 }
8499 my $GzipCmd = get_CmdPath("gzip");
8500 if(not $GzipCmd) {
8501 exitStatus("Not_Found", "can't find \"gzip\"");
8502 }
8503 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
8504 unlink($Pkg);
8505 chdir($From);
8506 system($TarCmd, "-czf", $Pkg, $Name);
8507 if($?)
8508 { # cannot allocate memory (or other problems with "tar")
8509 unlink($Path);
8510 exitStatus("Error", "can't pack the ABI dump: ".$!);
8511 }
8512 chdir($ORIG_DIR);
8513 unlink($Path);
8514 return $To."/".$Name.".tar.gz";
8515 }
8516}
8517
8518sub is_header_file($)
8519{
8520 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
8521 return $_[0];
8522 }
8523 return 0;
8524}
8525
8526sub is_not_header($)
8527{
8528 if($_[0]=~/\.\w+\Z/
8529 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
8530 return 1;
8531 }
8532 return 0;
8533}
8534
8535sub is_header($$$)
8536{
8537 my ($Header, $UserDefined, $LibVersion) = @_;
8538 return 0 if(-d $Header);
8539 if(-f $Header) {
8540 $Header = get_abs_path($Header);
8541 }
8542 else
8543 {
8544 if(is_abs($Header))
8545 { # incorrect absolute path
8546 return 0;
8547 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008548 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008549 $Header = $HPath;
8550 }
8551 else
8552 { # can't find header
8553 return 0;
8554 }
8555 }
8556 if($Header=~/\.\w+\Z/)
8557 { # have an extension
8558 return is_header_file($Header);
8559 }
8560 else
8561 {
8562 if($UserDefined==2)
8563 { # specified on the command line
8564 if(cmd_file($Header)!~/HTML|XML/i) {
8565 return $Header;
8566 }
8567 }
8568 elsif($UserDefined)
8569 { # specified in the XML-descriptor
8570 # header file without an extension
8571 return $Header;
8572 }
8573 else
8574 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008575 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008576 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008577 { # !~/HTML|XML|shared|dynamic/i
8578 return $Header;
8579 }
8580 }
8581 }
8582 return 0;
8583}
8584
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008585sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008586{
8587 my $LibVersion = $_[0];
8588 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
8589 {
8590 my $RegDir = get_dirname($RegHeader);
8591 $TargetHeaders{$LibVersion}{get_filename($RegHeader)}=1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008592
8593 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
8594 detect_recursive_includes($RegHeader, $LibVersion);
8595 }
8596
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008597 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
8598 {
8599 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008600
8601 if(familiarDirs($Dir, $RegDir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008602 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
8603 { # in the same directory or included by #include "..."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008604 $TargetHeaders{$LibVersion}{get_filename($RecInc)}=1;
8605 }
8606 }
8607 }
8608}
8609
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008610sub familiarDirs($$)
8611{
8612 my ($D1, $D2) = @_;
8613 if($D1 eq $D2) {
8614 return 1;
8615 }
8616 while($D1=~s/[\/\\]+.*?\Z//)
8617 {
8618 $D2=~s/[\/\\]+.*?\Z//;
8619 if($D1 eq "/usr/include") {
8620 return 0;
8621 }
8622 if($D1 eq $D2) {
8623 return 1;
8624 }
8625 }
8626 return 0;
8627}
8628
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008629sub readHeaders($)
8630{
8631 $Version = $_[0];
8632 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
8633 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008634 if($Debug)
8635 { # debug mode
8636 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008637 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008638 }
8639 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008640}
8641
8642sub prepareTypes($)
8643{
8644 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008645 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008646 { # support for old ABI dumps
8647 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008648 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008649 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008650 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
8651 if($TName=~/\A(\w+)::(\w+)/) {
8652 my ($P1, $P2) = ($1, $2);
8653 if($P1 eq $P2) {
8654 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008655 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008656 else {
8657 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
8658 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008659 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008660 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008661 }
8662 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008663 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008664 { # support for old ABI dumps
8665 # V < 2.5: array size == "number of elements"
8666 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008667 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008668 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008669 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008670 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008671 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008672 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008673 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008674 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008675 $Size *= $Base{"Size"};
8676 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008677 }
8678 else
8679 { # array[] is a pointer
8680 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008681 }
8682 }
8683 }
8684 }
8685 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008686 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008687 { # support for old ABI dumps
8688 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008689 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008690 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008691 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008692 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008693 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008694 my %Type = get_Type($TypeId, $LibVersion);
8695 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
8696 my %Type2 = get_Type($TypeId_2, $V2);
8697 if($Type{"Size"} ne $Type2{"Size"}) {
8698 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008699 }
8700 }
8701 }
8702 }
8703}
8704
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008705sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008706{
8707 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008708
8709 if(not keys(%{$SymbolInfo{$LibVersion}}))
8710 { # check if input is valid
8711 if(not $ExtendedCheck and not $CheckObjectsOnly)
8712 {
8713 if($CheckHeadersOnly) {
8714 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
8715 }
8716 else {
8717 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
8718 }
8719 }
8720 }
8721
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008722 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008723 if(not checkDump(1, "2.10")
8724 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008725 { # different formats
8726 $Remangle = 1;
8727 }
8728 if($CheckHeadersOnly)
8729 { # different languages
8730 if($UserLang)
8731 { # --lang=LANG for both versions
8732 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
8733 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
8734 {
8735 if($UserLang eq "C++")
8736 { # remangle symbols
8737 $Remangle = 1;
8738 }
8739 elsif($UserLang eq "C")
8740 { # remove mangling
8741 $Remangle = -1;
8742 }
8743 }
8744 }
8745 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008746
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008747 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008748 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008749 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04008750 { # support for old ABI dumps
8751 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
8752 {
8753 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
8754 {
8755 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
8756 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008757 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04008758 if(defined $DVal and $DVal ne "")
8759 {
8760 if($TName eq "char") {
8761 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
8762 }
8763 elsif($TName eq "bool") {
8764 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
8765 }
8766 }
8767 }
8768 }
8769 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008770 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008771 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008772 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
8773 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008774 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008775 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
8776 # + support for old ABI dumps
8777 next;
8778 }
8779 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008780 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008781 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008782 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008783 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008784
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008785 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008786 if(not checkDump(1, "2.12")
8787 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008788 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008789 if($ShortName eq "operator>>")
8790 {
8791 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
8792 { # corrected mangling of operator>>
8793 $SRemangle = 1;
8794 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008795 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008796 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
8797 {
8798 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
8799 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
8800 { # corrected mangling of const global data
8801 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
8802 # and incorrectly mangled by old ACC versions
8803 $SRemangle = 1;
8804 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008805 }
8806 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008807 if(not $CheckHeadersOnly)
8808 { # support for old ABI dumps
8809 if(not checkDump(1, "2.17")
8810 or not checkDump(2, "2.17"))
8811 {
8812 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
8813 {
8814 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
8815 {
8816 if(link_symbol($ShortName, $LibVersion, "-Deps"))
8817 {
8818 $MnglName = $ShortName;
8819 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
8820 }
8821 }
8822 }
8823 }
8824 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008825 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008826 { # support for old ABI dumps: some symbols are not mangled in old dumps
8827 # mangle both sets of symbols (old and new)
8828 # NOTE: remangling all symbols by the same mangler
8829 if($MnglName=~/\A_ZN(V|)K/)
8830 { # mangling may be incorrect on old ABI dumps
8831 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008832 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008833 }
8834 if($MnglName=~/\A_ZN(K|)V/)
8835 { # mangling may be incorrect on old ABI dumps
8836 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008837 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008838 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008839 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
8840 or (not $ClassID and $CheckHeadersOnly)
8841 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
8842 { # support for old ABI dumps, GCC >= 4.0
8843 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008844 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008845 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008846 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008847 $MangledNames{$LibVersion}{$MnglName} = 1;
8848 }
8849 }
8850 }
8851 elsif($Remangle==-1)
8852 { # remove mangling
8853 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008854 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008855 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008856 if(not $MnglName) {
8857 next;
8858 }
8859 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
8860 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008861 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
8862
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008863 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008864 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008865 { # support for old dumps
8866 # add "Volatile" attribute
8867 if($MnglName=~/_Z(K|)V/) {
8868 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
8869 }
8870 }
8871 # symbol and its symlink have same signatures
8872 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008873 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008874 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008875
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008876 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
8877 {
8878 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
8879 if($SymVer{$LibVersion}{$Alias}) {
8880 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
8881 }
8882 }
8883
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008884 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008885 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008886 }
8887 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
8888 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
8889 }
8890 if($ExtendedCheck)
8891 { # --ext option
8892 addExtension($LibVersion);
8893 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008894
8895 # clean memory
8896 delete($SymbolInfo{$LibVersion});
8897
8898 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008899 { # detect allocable classes with public exported constructors
8900 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008901 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008902 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008903 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008904 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008905 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
8906 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008907 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008908 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008909 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008910 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008911 $AllocableClass{$LibVersion}{$ClassName} = 1;
8912 }
8913 }
8914 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008915 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008916 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008917 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008918 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008919 if($CheckHeadersOnly)
8920 {
8921 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
8922 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
8923 { # all symbols except non-virtual inline
8924 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
8925 }
8926 }
8927 else {
8928 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008929 }
8930 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008931 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008932 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008933 }
8934 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008935 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008936 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008937 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008938 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008939 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008940 if(defined $Base{"Type"}
8941 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008942 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008943 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008944 if($Name=~/<([^<>\s]+)>/)
8945 {
8946 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
8947 $ReturnedClass{$LibVersion}{$Tid} = 1;
8948 }
8949 }
8950 else {
8951 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
8952 }
8953 }
8954 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008955 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008956 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008957 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008958 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008959 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008960 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008961 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008962 if($Base{"Type"}=~/Struct|Class/)
8963 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008964 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008965 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
8966 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008967 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008968 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008969 }
8970 }
8971 }
8972 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008973
8974 # mapping {short name => symbols}
8975 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008976 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008977 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008978 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008979 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008980 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008981 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008982 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008983 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
8984 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008985 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008986 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008987 }
8988 }
8989 }
8990 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008991
8992 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008993 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008994 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008995 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008996 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008997 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
8998 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008999 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009000 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009001 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009002 $ClassNames{$LibVersion}{$TName} = 1;
9003 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009004 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009005 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9006 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009007 }
9008 }
9009 }
9010 }
9011 }
9012}
9013
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009014sub register_TypeUsage($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009015{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009016 my ($TypeId, $LibVersion) = @_;
9017 if(not $TypeId) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009018 return 0;
9019 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009020 if($UsedType{$LibVersion}{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009021 { # already registered
9022 return 1;
9023 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009024 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009025 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009026 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009027 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|MethodPtr|FieldPtr|Enum)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009028 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009029 $UsedType{$LibVersion}{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009030 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009031 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009032 foreach my $BaseId (keys(%{$TInfo{"Base"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009033 { # register base classes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009034 register_TypeUsage($BaseId, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009035 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009036 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9037 {
9038 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9039 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009040 register_TypeUsage($TTid, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009041 }
9042 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009043 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009044 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009045 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009046 if(my $MTid = $TInfo{"Memb"}{$Memb_Pos}{"type"}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009047 register_TypeUsage($MTid, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009048 }
9049 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009050 if($TInfo{"Type"} eq "FuncPtr"
9051 or $TInfo{"Type"} eq "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009052 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009053 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009054 register_TypeUsage($RTid, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009055 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009056 foreach my $Memb_Pos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009057 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009058 if(my $MTid = $TInfo{"Param"}{$Memb_Pos}{"type"}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009059 register_TypeUsage($MTid, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009060 }
9061 }
9062 }
9063 return 1;
9064 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009065 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009066 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009067 $UsedType{$LibVersion}{$TypeId} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009068 register_TypeUsage($TInfo{"BaseType"}, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009069 return 1;
9070 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009071 elsif($TInfo{"Type"} eq "Intrinsic")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009072 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009073 $UsedType{$LibVersion}{$TypeId} = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009074 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009075 }
9076 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009077 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009078}
9079
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009080sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009081{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009082 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9083
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009084 if($Level eq "Dump")
9085 {
9086 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9087 { # TODO: check if this symbol is from
9088 # base classes of other target symbols
9089 return 1;
9090 }
9091 }
9092
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009093 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9094 { # stdc++ interfaces
9095 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009096 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009097
9098 my $Target = 0;
9099 if(my $Header = $SInfo->{"Header"}) {
9100 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9101 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009102 if($ExtendedCheck)
9103 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009104 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009105 $Target = 1;
9106 }
9107 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009108 if($CheckHeadersOnly)
9109 {
9110 if($Target)
9111 {
9112 if($Level eq "Dump")
9113 { # dumped
9114 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009115 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009116 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009117 return 1;
9118 }
9119 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009120 else {
9121 return 1;
9122 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009123 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009124 elsif($Level eq "Source")
9125 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009126 return 1;
9127 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009128 elsif($Level eq "Binary")
9129 { # checked
9130 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9131 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9132 return 1;
9133 }
9134 }
9135 }
9136 }
9137 else
9138 { # library is available
9139 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9140 { # exported symbols
9141 return 1;
9142 }
9143 if($Level eq "Dump")
9144 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009145 if($BinaryOnly)
9146 {
9147 if($SInfo->{"Data"})
9148 {
9149 if($Target) {
9150 return 1;
9151 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009152 }
9153 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009154 else
9155 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009156 if($Target) {
9157 return 1;
9158 }
9159 }
9160 }
9161 elsif($Level eq "Source")
9162 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009163 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
9164 or isInLineInst($Symbol, $SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009165 { # skip LOCAL symbols
9166 if($Target) {
9167 return 1;
9168 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009169 }
9170 }
9171 elsif($Level eq "Binary")
9172 { # checked
9173 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9174 {
9175 if($Target) {
9176 return 1;
9177 }
9178 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009179 }
9180 }
9181 return 0;
9182}
9183
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009184sub cleanDump($)
9185{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009186 my $LibVersion = $_[0];
9187 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9188 {
9189 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
9190 if(not $MnglName) {
9191 delete($SymbolInfo{$LibVersion}{$InfoId});
9192 next;
9193 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009194 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009195 if(not $ShortName) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009196 delete($SymbolInfo{$LibVersion}{$InfoId});
9197 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009198 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009199 if($MnglName eq $ShortName)
9200 { # remove duplicate data
9201 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009202 }
9203 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9204 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9205 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009206 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9207 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9208 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009209 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009210 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009211 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009212 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009213 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009214 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009215 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9216 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9217 }
9218 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009219 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9220 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9221 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009222 }
9223}
9224
9225sub selectType($$)
9226{
9227 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009228
9229 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9230 {
9231 if(defined $TypeInfo{$LibVersion}{$Dupl})
9232 {
9233 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9234 { # duplicate
9235 return 0;
9236 }
9237 }
9238 }
9239
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009240 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
9241 {
9242 if(not isBuiltIn($THeader))
9243 {
9244 if($TypeInfo{$LibVersion}{$Tid}{"Type"}=~/Class|Struct|Union|Enum|Typedef/)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009245 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009246 if(not isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"}))
9247 {
9248 if(is_target_header($THeader, $LibVersion))
9249 { # from target headers
9250 if(not selfTypedef($Tid, $LibVersion)) {
9251 return 1;
9252 }
9253 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009254 }
9255 }
9256 }
9257 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009258 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009259}
9260
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009261sub removeUnused($$)
9262{ # remove unused data types from the ABI dump
9263 my ($LibVersion, $Kind) = @_;
9264 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9265 {
9266 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9267 if(my $RTid = $FuncInfo{"Return"}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009268 register_TypeUsage($RTid, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009269 }
9270 if(my $FCid = $FuncInfo{"Class"})
9271 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009272 register_TypeUsage($FCid, $LibVersion);
9273 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009274 { # register "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009275 $UsedType{$LibVersion}{$ThisId} = 1;
9276 if(my %ThisType = get_Type($ThisId, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009277 register_TypeUsage($ThisType{"BaseType"}, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009278 }
9279 }
9280 }
9281 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9282 {
9283 if(my $PTid = $FuncInfo{"Param"}{$PPos}{"type"}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009284 register_TypeUsage($PTid, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009285 }
9286 }
9287 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9288 {
9289 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9290 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009291 register_TypeUsage($TTid, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009292 }
9293 }
9294 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009295 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
9296 {
9297 if($UsedType{$LibVersion}{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009298 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009299 next;
9300 }
9301
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009302 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009303 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009304 if(selectType($Tid, $LibVersion)) {
9305 register_TypeUsage($Tid, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009306 }
9307 }
9308 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009309 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
9310 { # remove unused types
9311 if($UsedType{$LibVersion}{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009312 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009313 next;
9314 }
9315 # remove type
9316 delete($TypeInfo{$LibVersion}{$Tid});
9317 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009318
9319 # clean memory
9320 %UsedType = ();
9321}
9322
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009323sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009324{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009325 my ($TypeId, $LibVersion) = @_;
9326 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009327 if($Type{"Type"} eq "Typedef")
9328 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009329 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009330 if($Base{"Type"}=~/Class|Struct/)
9331 {
9332 if($Type{"Name"} eq $Base{"Name"}) {
9333 return 1;
9334 }
9335 elsif($Type{"Name"}=~/::(\w+)\Z/)
9336 {
9337 if($Type{"Name"} eq $Base{"Name"}."::".$1)
9338 { # QPointer<QWidget>::QPointer
9339 return 1;
9340 }
9341 }
9342 }
9343 }
9344 return 0;
9345}
9346
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009347sub addExtension($)
9348{
9349 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009350 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009351 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009352 if(selectType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009353 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009354 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
9355 $TName=~s/\A(struct|union|class|enum) //;
9356 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009357
9358 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
9359 "Header" => "extended.h",
9360 "ShortName" => $Symbol,
9361 "MnglName" => $Symbol,
9362 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
9363 );
9364
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009365 $ExtendedSymbols{$Symbol} = 1;
9366 $CheckedSymbols{"Binary"}{$Symbol} = 1;
9367 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009368 }
9369 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009370 $ExtendedSymbols{"external_func_0"} = 1;
9371 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
9372 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009373}
9374
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009375sub findMethod($$$)
9376{
9377 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009378 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009379 {
9380 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
9381 return $VirtMethodInClass;
9382 }
9383 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
9384 return $VirtMethodInBaseClasses;
9385 }
9386 }
9387 return "";
9388}
9389
9390sub findMethod_Class($$$)
9391{
9392 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009393 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009394 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
9395 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
9396 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
9397 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
9398 { # search for interface with the same parameters suffix (overridden)
9399 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
9400 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04009401 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
9402 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009403 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
9404 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009405 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
9406 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
9407 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
9408 return $Candidate;
9409 }
9410 }
9411 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04009412 else
9413 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009414 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
9415 return $Candidate;
9416 }
9417 }
9418 }
9419 }
9420 return "";
9421}
9422
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009423sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009424{
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009425 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009426 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009427 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009428 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
9429 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009430 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009431 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009432 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009433 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
9434 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009435 { # pure virtual D2-destructors are marked as "virt" in the dump
9436 # virtual D2-destructors are NOT marked as "virt" in the dump
9437 # both destructors are not presented in the v-table
9438 next;
9439 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009440 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009441 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
9442 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009443 }
9444}
9445
9446sub registerOverriding($)
9447{
9448 my $LibVersion = $_[0];
9449 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009450 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009451 foreach my $ClassName (@Classes)
9452 {
9453 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
9454 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009455 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
9456 { # pure virtuals
9457 next;
9458 }
9459 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
9460 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009461 {
9462 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
9463 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
9464 { # both overridden virtual methods
9465 # and implemented pure virtual methods
9466 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
9467 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
9468 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
9469 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009470 }
9471 }
9472 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
9473 delete($VirtualTable{$LibVersion}{$ClassName});
9474 }
9475 }
9476}
9477
9478sub setVirtFuncPositions($)
9479{
9480 my $LibVersion = $_[0];
9481 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
9482 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009483 my ($Num, $Rel) = (1, 0);
9484
9485 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009486 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009487 if($UsedDump{$LibVersion}{"DWARF"}) {
9488 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
9489 }
9490 else {
9491 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
9492 }
9493 foreach my $VirtFunc (@Funcs)
9494 {
9495 if($UsedDump{$LibVersion}{"DWARF"}) {
9496 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
9497 }
9498 else {
9499 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
9500 }
9501
9502 # set relative positions
9503 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
9504 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
9505 { # relative position excluding added and removed virtual functions
9506 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
9507 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
9508 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
9509 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009510 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009511 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009512 }
9513 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009514 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009515 {
9516 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009517 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009518 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009519 }
9520 }
9521}
9522
9523sub get_sub_classes($$$)
9524{
9525 my ($ClassId, $LibVersion, $Recursive) = @_;
9526 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
9527 my @Subs = ();
9528 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
9529 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009530 if($Recursive)
9531 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009532 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
9533 push(@Subs, $SubSubId);
9534 }
9535 }
9536 push(@Subs, $SubId);
9537 }
9538 return @Subs;
9539}
9540
9541sub get_base_classes($$$)
9542{
9543 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009544 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009545 return () if(not defined $ClassType{"Base"});
9546 my @Bases = ();
9547 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
9548 keys(%{$ClassType{"Base"}}))
9549 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009550 if($Recursive)
9551 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009552 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
9553 push(@Bases, $SubBaseId);
9554 }
9555 }
9556 push(@Bases, $BaseId);
9557 }
9558 return @Bases;
9559}
9560
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009561sub getVTable_Model($$)
9562{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009563 my ($ClassId, $LibVersion) = @_;
9564 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
9565 my @Elements = ();
9566 foreach my $BaseId (@Bases, $ClassId)
9567 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009568 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009569 {
9570 if(defined $VirtualTable{$LibVersion}{$BName})
9571 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009572 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
9573 if($UsedDump{$LibVersion}{"DWARF"}) {
9574 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
9575 }
9576 else {
9577 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
9578 }
9579 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009580 push(@Elements, $VFunc);
9581 }
9582 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009583 }
9584 }
9585 return @Elements;
9586}
9587
9588sub getVShift($$)
9589{
9590 my ($ClassId, $LibVersion) = @_;
9591 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
9592 my $VShift = 0;
9593 foreach my $BaseId (@Bases)
9594 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009595 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009596 {
9597 if(defined $VirtualTable{$LibVersion}{$BName}) {
9598 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
9599 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009600 }
9601 }
9602 return $VShift;
9603}
9604
9605sub getShift($$)
9606{
9607 my ($ClassId, $LibVersion) = @_;
9608 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
9609 my $Shift = 0;
9610 foreach my $BaseId (@Bases)
9611 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009612 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009613 {
9614 if($Size!=1)
9615 { # not empty base class
9616 $Shift+=$Size;
9617 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009618 }
9619 }
9620 return $Shift;
9621}
9622
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009623sub getVTable_Size($$)
9624{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009625 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009626 my $Size = 0;
9627 # three approaches
9628 if(not $Size)
9629 { # real size
9630 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
9631 $Size = keys(%VTable);
9632 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009633 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009634 if(not $Size)
9635 { # shared library symbol size
9636 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
9637 $Size /= $WORD_SIZE{$LibVersion};
9638 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009639 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009640 if(not $Size)
9641 { # model size
9642 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
9643 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
9644 }
9645 }
9646 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009647}
9648
9649sub isCopyingClass($$)
9650{
9651 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009652 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009653}
9654
9655sub isLeafClass($$)
9656{
9657 my ($ClassId, $LibVersion) = @_;
9658 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
9659}
9660
9661sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009662{ # check structured type for public fields
9663 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009664}
9665
9666sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009667{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009668 my ($TypePtr, $Skip, $Start, $End) = @_;
9669 return 0 if(not $TypePtr);
9670 if($End==-1) {
9671 $End = keys(%{$TypePtr->{"Memb"}})-1;
9672 }
9673 foreach my $MemPos (keys(%{$TypePtr->{"Memb"}}))
9674 {
9675 if($Skip and $Skip->{$MemPos})
9676 { # skip removed/added fields
9677 next;
9678 }
9679 if(int($MemPos)>=$Start and int($MemPos)<=$End)
9680 {
9681 if(isPublic($TypePtr, $MemPos)) {
9682 return ($MemPos+1);
9683 }
9684 }
9685 }
9686 return 0;
9687}
9688
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009689sub isReserved($)
9690{ # reserved fields == private
9691 my $MName = $_[0];
9692 if($MName=~/reserved|padding|f_spare/i) {
9693 return 1;
9694 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009695 if($MName=~/\A[_]*(spare|pad|unused)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009696 return 1;
9697 }
9698 if($MName=~/(pad\d+)/i) {
9699 return 1;
9700 }
9701 return 0;
9702}
9703
9704sub isPublic($$)
9705{
9706 my ($TypePtr, $FieldPos) = @_;
9707 return 0 if(not $TypePtr);
9708 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
9709 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
9710 if(not $TypePtr->{"Memb"}{$FieldPos}{"access"})
9711 { # by name in C language
9712 # FIXME: add other methods to detect private members
9713 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
9714 if($MName=~/priv|abidata|parent_object/i)
9715 { # C-styled private data
9716 return 0;
9717 }
9718 if(lc($MName) eq "abi")
9719 { # ABI information/reserved field
9720 return 0;
9721 }
9722 if(isReserved($MName))
9723 { # reserved fields
9724 return 0;
9725 }
9726 return 1;
9727 }
9728 elsif($TypePtr->{"Memb"}{$FieldPos}{"access"} ne "private")
9729 { # by access in C++ language
9730 return 1;
9731 }
9732 return 0;
9733}
9734
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009735sub getVTable_Real($$)
9736{
9737 my ($ClassName, $LibVersion) = @_;
9738 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9739 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009740 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009741 if(defined $Type{"VTable"}) {
9742 return %{$Type{"VTable"}};
9743 }
9744 }
9745 return ();
9746}
9747
9748sub cmpVTables($)
9749{
9750 my $ClassName = $_[0];
9751 my $Res = cmpVTables_Real($ClassName, 1);
9752 if($Res==-1) {
9753 $Res = cmpVTables_Model($ClassName);
9754 }
9755 return $Res;
9756}
9757
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009758sub cmpVTables_Model($)
9759{
9760 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009761 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009762 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009763 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009764 return 1;
9765 }
9766 }
9767 return 0;
9768}
9769
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009770sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009771{
9772 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009773 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
9774 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009775 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009776 my %VTable_Old = getVTable_Real($ClassName, 1);
9777 my %VTable_New = getVTable_Real($ClassName, 2);
9778 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009779 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009780 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009781 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009782 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009783 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
9784 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009785 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009786 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009787 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009788 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009789 my $Entry1 = $VTable_Old{$Offset};
9790 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009791 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009792 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009793 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009794 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009795 $Entry1 = simpleVEntry($Entry1);
9796 $Entry2 = simpleVEntry($Entry2);
9797 if($Entry1 ne $Entry2)
9798 { # register as changed
9799 if($Entry1=~/::([^:]+)\Z/)
9800 {
9801 my $M1 = $1;
9802 if($Entry2=~/::([^:]+)\Z/)
9803 {
9804 my $M2 = $1;
9805 if($M1 eq $M2)
9806 { # overridden
9807 next;
9808 }
9809 }
9810 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009811 if(differentDumps("G"))
9812 {
9813 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
9814 {
9815 # GCC 4.6.1: -0x00000000000000010
9816 # GCC 4.7.0: -16
9817 next;
9818 }
9819 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009820 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009821 }
9822 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009823 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009824}
9825
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009826sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009827{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009828 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009829 foreach my $ClassName (keys(%{$VirtualTable{1}}))
9830 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009831 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009832 { # already registered
9833 next;
9834 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009835 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009836 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009837 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009838 foreach my $Symbol (@Affected)
9839 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009840 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009841 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009842 "Target"=>$ClassName);
9843 }
9844 }
9845 }
9846}
9847
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009848sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009849{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009850 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009851 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009852 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009853 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009854 next if(not $ClassId);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009855 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009856 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009857 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009858 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009859 if($TName_Tid{1}{$ClassName}
9860 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009861 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009862 if(defined $CompleteSignature{1}{$Symbol}
9863 and $CompleteSignature{1}{$Symbol}{"Virt"})
9864 { # override some method in v.1
9865 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009866 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009867 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009868 }
9869 }
9870 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009871 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009872 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009873 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009874 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009875 if($TName_Tid{2}{$ClassName}
9876 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009877 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009878 if(defined $CompleteSignature{2}{$Symbol}
9879 and $CompleteSignature{2}{$Symbol}{"Virt"})
9880 { # override some method in v.2
9881 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009882 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009883 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009884 }
9885 }
9886 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009887 if($Level eq "Binary")
9888 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009889 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009890 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
9891 { # check replacements, including pure virtual methods
9892 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
9893 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009894 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009895 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
9896 if($AddedPos==$RemovedPos)
9897 {
9898 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
9899 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
9900 last; # other methods will be reported as "added" or "removed"
9901 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009902 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009903 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
9904 {
9905 if(lc($AddedVFunc) eq lc($RemovedVFunc))
9906 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009907 next;
9908 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009909 my $ProblemType = "Virtual_Replacement";
9910 my @Affected = ($RemovedVFunc);
9911 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
9912 { # pure methods
9913 if(not isUsedClass($ClassId, 1, $Level))
9914 { # not a parameter of some exported method
9915 next;
9916 }
9917 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009918
9919 # affected all methods (both virtual and non-virtual ones)
9920 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
9921 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009922 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009923 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009924 foreach my $AffectedInt (@Affected)
9925 {
9926 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
9927 { # affected exported methods only
9928 next;
9929 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009930 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
9931 next;
9932 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009933 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
9934 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009935 "Target"=>get_Signature($AddedVFunc, 2),
9936 "Old_Value"=>get_Signature($RemovedVFunc, 1));
9937 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009938 }
9939 }
9940 }
9941 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009942 if(not checkDump(1, "2.0")
9943 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009944 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009945 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009946 return;
9947 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009948 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009949 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009950 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009951 next if(not $ClassId_Old);
9952 if(not isCreatable($ClassId_Old, 1))
9953 { # skip classes without public constructors (including auto-generated)
9954 # example: class has only a private exported or private inline constructor
9955 next;
9956 }
9957 if($ClassName=~/>/)
9958 { # skip affected template instances
9959 next;
9960 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009961 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009962 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009963 if(not $ClassId_New) {
9964 next;
9965 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009966 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009967 if($Class_New{"Type"}!~/Class|Struct/)
9968 { # became typedef
9969 if($Level eq "Binary") {
9970 next;
9971 }
9972 if($Level eq "Source")
9973 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009974 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009975 if($Class_New{"Type"}!~/Class|Struct/) {
9976 next;
9977 }
9978 $ClassId_New = $Class_New{"Tid"};
9979 }
9980 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009981 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
9982 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 +04009983
9984 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
9985 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
9986
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009987 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009988 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
9989 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009990 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
9991 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009992 my $Shift_Old = getShift($ClassId_Old, 1);
9993 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009994 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009995 my ($Added, $Removed) = (0, 0);
9996 my @StableBases_Old = ();
9997 foreach my $BaseId (@Bases_Old)
9998 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009999 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010000 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010001 push(@StableBases_Old, $BaseId);
10002 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010003 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010004 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010005 { # removed base
10006 # excluding namespace::SomeClass to SomeClass renaming
10007 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010008 if($Level eq "Binary")
10009 { # Binary-level
10010 if($Shift_Old ne $Shift_New)
10011 { # affected fields
10012 if(havePubFields(\%Class_Old)) {
10013 $ProblemKind .= "_And_Shift";
10014 }
10015 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10016 $ProblemKind .= "_And_Size";
10017 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010018 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010019 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10020 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010021 { # affected v-table
10022 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010023 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010024 }
10025 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010026 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010027 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10028 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010029 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10030 {
10031 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10032 if($ProblemKind=~/VTable/) {
10033 $VTableChanged_M{$SubName}=1;
10034 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010035 }
10036 }
10037 foreach my $Interface (@Affected)
10038 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010039 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10040 next;
10041 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010042 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010043 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010044 "Target"=>$BaseName,
10045 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10046 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10047 "Shift"=>abs($Shift_New-$Shift_Old) );
10048 }
10049 $Removed+=1;
10050 }
10051 }
10052 my @StableBases_New = ();
10053 foreach my $BaseId (@Bases_New)
10054 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010055 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010056 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010057 push(@StableBases_New, $BaseId);
10058 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010059 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010060 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010061 { # added base
10062 # excluding namespace::SomeClass to SomeClass renaming
10063 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010064 if($Level eq "Binary")
10065 { # Binary-level
10066 if($Shift_Old ne $Shift_New)
10067 { # affected fields
10068 if(havePubFields(\%Class_Old)) {
10069 $ProblemKind .= "_And_Shift";
10070 }
10071 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10072 $ProblemKind .= "_And_Size";
10073 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010074 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010075 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10076 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010077 { # affected v-table
10078 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010079 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010080 }
10081 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010082 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010083 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10084 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010085 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10086 {
10087 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10088 if($ProblemKind=~/VTable/) {
10089 $VTableChanged_M{$SubName}=1;
10090 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010091 }
10092 }
10093 foreach my $Interface (@Affected)
10094 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010095 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10096 next;
10097 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010098 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010099 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010100 "Target"=>$BaseName,
10101 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10102 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10103 "Shift"=>abs($Shift_New-$Shift_Old) );
10104 }
10105 $Added+=1;
10106 }
10107 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010108 if($Level eq "Binary")
10109 { # Binary-level
10110 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010111 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10112 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010113 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010114 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010115 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010116 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010117 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010118 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10119 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010120 if($NewPos!=$OldPos)
10121 { # changed position of the base class
10122 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010123 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010124 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10125 next;
10126 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010127 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10128 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010129 "Target"=>$BaseName,
10130 "Old_Value"=>$OldPos-1,
10131 "New_Value"=>$NewPos-1 );
10132 }
10133 }
10134 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10135 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10136 { # became non-virtual base
10137 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10138 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010139 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10140 next;
10141 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010142 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10143 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010144 "Target"=>$BaseName );
10145 }
10146 }
10147 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10148 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10149 { # became virtual base
10150 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10151 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010152 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10153 next;
10154 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010155 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10156 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010157 "Target"=>$BaseName );
10158 }
10159 }
10160 }
10161 }
10162 # detect size changes in base classes
10163 if($Shift_Old!=$Shift_New)
10164 { # size of allocable class
10165 foreach my $BaseId (@StableBases_Old)
10166 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010167 my %BaseType = get_Type($BaseId, 1);
10168 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010169 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010170 if($Size_Old ne $Size_New
10171 and $Size_Old and $Size_New)
10172 {
10173 my $ProblemType = "";
10174 if(isCopyingClass($BaseId, 1)) {
10175 $ProblemType = "Size_Of_Copying_Class";
10176 }
10177 elsif($AllocableClass{1}{$BaseType{"Name"}})
10178 {
10179 if($Size_New>$Size_Old)
10180 { # increased size
10181 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010182 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010183 else
10184 { # decreased size
10185 $ProblemType = "Size_Of_Allocable_Class_Decreased";
10186 if(not havePubFields(\%Class_Old))
10187 { # affected class has no public members
10188 next;
10189 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010190 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010191 }
10192 next if(not $ProblemType);
10193 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10194 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010195 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10196 next;
10197 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010198 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
10199 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010200 "Target"=>$BaseType{"Name"},
10201 "Old_Size"=>$Size_Old*$BYTE_SIZE,
10202 "New_Size"=>$Size_New*$BYTE_SIZE );
10203 }
10204 }
10205 }
10206 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010207 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010208 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010209 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010210 { # compare virtual tables size in base classes
10211 my $VShift_Old = getVShift($ClassId_Old, 1);
10212 my $VShift_New = getVShift($ClassId_New, 2);
10213 if($VShift_Old ne $VShift_New)
10214 { # changes in the base class or changes in the list of base classes
10215 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
10216 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
10217 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010218 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010219 foreach my $BaseId (@AllBases_Old)
10220 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010221 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010222 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010223 { # lost base
10224 next;
10225 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010226 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
10227 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010228 if($VSize_Old!=$VSize_New)
10229 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010230 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010231 { # TODO: affected non-virtual methods?
10232 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010233 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
10234 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010235 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010236 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010237 { # skip interfaces that have not changed the absolute virtual position
10238 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010239 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010240 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
10241 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010242 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010243 $VTableChanged_M{$BaseType{"Name"}} = 1;
10244 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010245 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
10246 { # the reason of the layout change: added virtual functions
10247 next if($VirtualReplacement{$VirtFunc});
10248 my $ProblemType = "Added_Virtual_Method";
10249 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
10250 $ProblemType = "Added_Pure_Virtual_Method";
10251 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010252 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010253 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010254 "Target"=>get_Signature($VirtFunc, 2) );
10255 }
10256 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
10257 { # the reason of the layout change: removed virtual functions
10258 next if($VirtualReplacement{$VirtFunc});
10259 my $ProblemType = "Removed_Virtual_Method";
10260 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
10261 $ProblemType = "Removed_Pure_Virtual_Method";
10262 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010263 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010264 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010265 "Target"=>get_Signature($VirtFunc, 1) );
10266 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010267 }
10268 }
10269 }
10270 }
10271 }
10272 }
10273 }
10274}
10275
10276sub isCreatable($$)
10277{
10278 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010279 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010280 or isCopyingClass($ClassId, $LibVersion)) {
10281 return 1;
10282 }
10283 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10284 { # Fix for incomplete data: if this class has
10285 # a base class then it should also has a constructor
10286 return 1;
10287 }
10288 if($ReturnedClass{$LibVersion}{$ClassId})
10289 { # returned by some method of this class
10290 # or any other class
10291 return 1;
10292 }
10293 return 0;
10294}
10295
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010296sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010297{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010298 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010299 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
10300 { # parameter of some exported method
10301 return 1;
10302 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010303 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
10304 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010305 { # method from target class
10306 return 1;
10307 }
10308 return 0;
10309}
10310
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010311sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010312{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010313 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010314 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010315 # - virtual
10316 # - pure-virtual
10317 # - non-virtual
10318 if($CompleteSignature{1}{$Interface}{"Data"})
10319 { # global data is not affected
10320 return;
10321 }
10322 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010323 if(not $Class_Id) {
10324 return;
10325 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010326 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010327 if(cmpVTables_Real($CName, 1)==0)
10328 { # no changes
10329 return;
10330 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010331 $CheckedTypes{$Level}{$CName} = 1;
10332 if($Level eq "Binary")
10333 { # Binary-level
10334 if($CompleteSignature{1}{$Interface}{"PureVirt"}
10335 and not isUsedClass($Class_Id, 1, $Level))
10336 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010337 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010338 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010339 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010340 }
10341 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
10342 {
10343 if(defined $VirtualTable{2}{$CName}{$Func}
10344 and defined $CompleteSignature{2}{$Func})
10345 {
10346 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
10347 and $CompleteSignature{2}{$Func}{"PureVirt"})
10348 { # became pure virtual
10349 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
10350 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010351 "Target"=>get_Signature_M($Func, 1) );
10352 $VTableChanged_M{$CName} = 1;
10353 }
10354 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
10355 and not $CompleteSignature{2}{$Func}{"PureVirt"})
10356 { # became non-pure virtual
10357 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
10358 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010359 "Target"=>get_Signature_M($Func, 1) );
10360 $VTableChanged_M{$CName} = 1;
10361 }
10362 }
10363 }
10364 if($Level eq "Binary")
10365 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010366 # check virtual table structure
10367 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
10368 {
10369 next if($Interface eq $AddedVFunc);
10370 next if($VirtualReplacement{$AddedVFunc});
10371 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
10372 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
10373 { # pure virtual methods affect all others (virtual and non-virtual)
10374 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010375 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010376 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010377 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010378 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010379 elsif(not defined $VirtualTable{1}{$CName}
10380 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010381 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010382 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010383 { # became polymorphous class, added v-table pointer
10384 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010385 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010386 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010387 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010388 }
10389 else
10390 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010391 my $VSize_Old = getVTable_Size($CName, 1);
10392 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010393 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010394 if(isCopyingClass($Class_Id, 1))
10395 { # class has no constructors and v-table will be copied by applications, this may affect all methods
10396 my $ProblemType = "Added_Virtual_Method";
10397 if(isLeafClass($Class_Id, 1)) {
10398 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
10399 }
10400 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10401 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010402 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010403 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010404 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010405 else
10406 {
10407 my $ProblemType = "Added_Virtual_Method";
10408 if(isLeafClass($Class_Id, 1)) {
10409 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
10410 }
10411 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10412 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010413 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010414 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010415 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010416 }
10417 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010418 elsif($CompleteSignature{1}{$Interface}{"Virt"}
10419 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010420 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010421 if(defined $VirtualTable{1}{$CName}
10422 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010423 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010424 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
10425 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010426
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010427 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010428 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010429 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
10430 foreach my $ASymbol (@Affected)
10431 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010432 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
10433 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010434 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010435 next;
10436 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010437 }
10438 $CheckedSymbols{$Level}{$ASymbol} = 1;
10439 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
10440 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010441 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010442 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010443 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010444 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010445 }
10446 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010447 else {
10448 # safe
10449 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010450 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010451 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
10452 {
10453 next if($VirtualReplacement{$RemovedVFunc});
10454 if($RemovedVFunc eq $Interface
10455 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10456 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010457 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010458 next;
10459 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010460 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010461 { # became non-polymorphous class, removed v-table pointer
10462 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
10463 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010464 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010465 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010466 }
10467 elsif($CompleteSignature{1}{$Interface}{"Virt"}
10468 or $CompleteSignature{1}{$Interface}{"PureVirt"})
10469 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010470 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010471 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010472 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
10473 next;
10474 }
10475 my $VPos_New = -1;
10476 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010477 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010478 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
10479 }
10480 else
10481 {
10482 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010483 next;
10484 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010485 }
10486 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
10487 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
10488 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
10489 {
10490 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
10491 foreach my $ASymbol (@Affected)
10492 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010493 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
10494 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010495 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010496 next;
10497 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010498 }
10499 my $ProblemType = "Removed_Virtual_Method";
10500 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
10501 $ProblemType = "Removed_Pure_Virtual_Method";
10502 }
10503 $CheckedSymbols{$Level}{$ASymbol} = 1;
10504 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
10505 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010506 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010507 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010508 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010509 }
10510 }
10511 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010512 }
10513 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010514 else
10515 { # Source-level
10516 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010517 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010518 next if($Interface eq $AddedVFunc);
10519 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010520 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010521 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
10522 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010523 "Target"=>get_Signature($AddedVFunc, 2) );
10524 }
10525 }
10526 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
10527 {
10528 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10529 {
10530 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
10531 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010532 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010533 }
10534 }
10535 }
10536}
10537
10538sub find_MemberPair_Pos_byName($$)
10539{
10540 my ($Member_Name, $Pair_Type) = @_;
10541 $Member_Name=~s/\A[_]+|[_]+\Z//g;
10542 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
10543 {
10544 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
10545 {
10546 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
10547 $Name=~s/\A[_]+|[_]+\Z//g;
10548 if($Name eq $Member_Name) {
10549 return $MemberPair_Pos;
10550 }
10551 }
10552 }
10553 return "lost";
10554}
10555
10556sub find_MemberPair_Pos_byVal($$)
10557{
10558 my ($Member_Value, $Pair_Type) = @_;
10559 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
10560 {
10561 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
10562 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
10563 return $MemberPair_Pos;
10564 }
10565 }
10566 return "lost";
10567}
10568
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010569my %Severity_Val=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010570 "High"=>3,
10571 "Medium"=>2,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010572 "Low"=>1,
10573 "Safe"=>-1
10574);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010575
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010576sub maxSeverity($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010577{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010578 my ($S1, $S2) = @_;
10579 if(cmpSeverities($S1, $S2)) {
10580 return $S1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010581 }
10582 else {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010583 return $S2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010584 }
10585}
10586
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010587sub cmpSeverities($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010588{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010589 my ($S1, $S2) = @_;
10590 if(not $S1) {
10591 return 0;
10592 }
10593 elsif(not $S2) {
10594 return 1;
10595 }
10596 return ($Severity_Val{$S1}>$Severity_Val{$S2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010597}
10598
10599sub getProblemSeverity($$)
10600{
10601 my ($Level, $Kind) = @_;
10602 return $CompatRules{$Level}{$Kind}{"Severity"};
10603}
10604
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010605sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010606{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010607 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010608 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010609 if( $_->{"T1"} eq $_[0]
10610 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010611 {
10612 return 1;
10613 }
10614 }
10615 return 0;
10616}
10617
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010618sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010619{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010620 my %IDs = (
10621 "T1" => $_[0],
10622 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010623 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010624 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010625}
10626
10627sub isRenamed($$$$$)
10628{
10629 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
10630 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
10631 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010632 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010633 if(not defined $Type2->{"Memb"}{$MemPos}) {
10634 return "";
10635 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010636 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010637 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010638
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010639 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
10640 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010641 if($MemberPair_Pos_Rev eq "lost")
10642 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010643 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
10644 { # base type match
10645 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010646 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010647 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
10648 { # exact type match
10649 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010650 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010651 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
10652 { # size match
10653 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010654 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010655 if(isReserved($Pair_Name))
10656 { # reserved fields
10657 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010658 }
10659 }
10660 return "";
10661}
10662
10663sub isLastElem($$)
10664{
10665 my ($Pos, $TypeRef) = @_;
10666 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
10667 if($Name=~/last|count|max|total/i)
10668 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
10669 return 1;
10670 }
10671 elsif($Name=~/END|NLIMITS\Z/)
10672 { # __RLIMIT_NLIMITS
10673 return 1;
10674 }
10675 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
10676 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
10677 { # NImageFormats, NColorRoles
10678 return 1;
10679 }
10680 return 0;
10681}
10682
10683sub nonComparable($$)
10684{
10685 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010686
10687 my $N1 = $T1->{"Name"};
10688 my $N2 = $T2->{"Name"};
10689
10690 $N1=~s/\A(struct|union|enum) //;
10691 $N2=~s/\A(struct|union|enum) //;
10692
10693 if($N1 ne $N2
10694 and not isAnon($N1)
10695 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010696 { # different names
10697 if($T1->{"Type"} ne "Pointer"
10698 or $T2->{"Type"} ne "Pointer")
10699 { # compare base types
10700 return 1;
10701 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010702 if($N1!~/\Avoid\s*\*/
10703 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010704 {
10705 return 1;
10706 }
10707 }
10708 elsif($T1->{"Type"} ne $T2->{"Type"})
10709 { # different types
10710 if($T1->{"Type"} eq "Class"
10711 and $T2->{"Type"} eq "Struct")
10712 { # "class" to "struct"
10713 return 0;
10714 }
10715 elsif($T2->{"Type"} eq "Class"
10716 and $T1->{"Type"} eq "Struct")
10717 { # "struct" to "class"
10718 return 0;
10719 }
10720 else
10721 { # "class" to "enum"
10722 # "union" to "class"
10723 # ...
10724 return 1;
10725 }
10726 }
10727 return 0;
10728}
10729
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010730sub isOpaque($)
10731{
10732 my $T = $_[0];
10733 if(not defined $T->{"Memb"})
10734 {
10735 return 1;
10736 }
10737 return 0;
10738}
10739
10740sub removeVPtr($)
10741{ # support for old ABI dumps
10742 my $TPtr = $_[0];
10743 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
10744 if($#Pos>=1)
10745 {
10746 foreach my $Pos (0 .. $#Pos-1)
10747 {
10748 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
10749 }
10750 delete($TPtr->{"Memb"}{$#Pos});
10751 }
10752}
10753
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010754sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010755{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010756 my ($Type1_Id, $Type2_Id, $Level) = @_;
10757 return () if(not $Type1_Id or not $Type2_Id);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010758 my (%Sub_SubProblems, %SubProblems) = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010759 if($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010760 { # already merged
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010761 return %{$Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010762 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010763 my %Type1 = get_Type($Type1_Id, 1);
10764 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010765 if(not $Type1{"Name"} or not $Type2{"Name"}) {
10766 return ();
10767 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010768
10769 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010770 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
10771 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010772 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
10773
10774 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
10775 {
10776 if($Type1_Pure{"Type"}=~/Struct|Union/
10777 and $Type2_Pure{"Type"}=~/Struct|Union/)
10778 {
10779 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
10780 {
10781 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
10782 "Target"=>$Type1_Pure{"Name"},
10783 "Type_Name"=>$Type1_Pure{"Name"} );
10784
10785 %{$Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id}} = %SubProblems;
10786 return %SubProblems;
10787 }
10788 }
10789 }
10790
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010791 if(not $Type1_Pure{"Size"} or not $Type2_Pure{"Size"})
10792 { # including a case when "class Class { ... };" changed to "class Class;"
10793 return ();
10794 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010795 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010796 { # skip recursive declarations
10797 return ();
10798 }
10799 return () if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
10800 return () if($SkipTypes{1}{$Type1_Pure{"Name"}});
10801 return () if($SkipTypes{1}{$Type1{"Name"}});
10802
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010803 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
10804 { # support for old ABI dumps
10805 # _vptr field added in 3.0
10806 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
10807 {
10808 if(defined $Type2_Pure{"Memb"}
10809 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
10810 {
10811 if(keys(%{$Type2_Pure{"Memb"}})==1) {
10812 delete($Type2_Pure{"Memb"}{0});
10813 }
10814 else {
10815 removeVPtr(\%Type2_Pure);
10816 }
10817 }
10818 }
10819 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
10820 {
10821 if(defined $Type1_Pure{"Memb"}
10822 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
10823 {
10824 if(keys(%{$Type1_Pure{"Memb"}})==1) {
10825 delete($Type1_Pure{"Memb"}{0});
10826 }
10827 else {
10828 removeVPtr(\%Type1_Pure);
10829 }
10830 }
10831 }
10832 }
10833
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010834 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
10835 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010836
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010837 if(not $UseOldDumps and %Typedef_1 and %Typedef_2
10838 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
10839 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010840 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010841 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
10842 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010843 if($Base_1{"Name"} ne $Base_2{"Name"})
10844 {
10845 if(differentDumps("G")
10846 or differentDumps("V"))
10847 { # different GCC versions or different dumps
10848 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
10849 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
10850 # std::__va_list and __va_list
10851 $Base_1{"Name"}=~s/\A(\w+::)+//;
10852 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010853 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
10854 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010855 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010856 }
10857 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
10858 and $Base_1{"Name"} ne $Base_2{"Name"})
10859 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010860 if($Level eq "Binary"
10861 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010862 {
10863 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
10864 "Target"=>$Typedef_1{"Name"},
10865 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010866 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
10867 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
10868 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010869 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
10870 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010871 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010872 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010873 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
10874 {
10875 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
10876 "Target"=>$Typedef_1{"Name"},
10877 "Type_Name"=>$Typedef_1{"Name"},
10878 "Old_Value"=>$Base_1{"Name"},
10879 "New_Value"=>$Base_2{"Name"} );
10880 }
10881 else
10882 {
10883 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
10884 "Target"=>$Typedef_1{"Name"},
10885 "Type_Name"=>$Typedef_1{"Name"},
10886 "Old_Value"=>$Base_1{"Name"},
10887 "New_Value"=>$Base_2{"Name"} );
10888 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010889 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010890 }
10891 }
10892 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
10893 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010894 my $TT1 = $Type1_Pure{"Type"};
10895 my $TT2 = $Type2_Pure{"Type"};
10896
10897 if($TT1 ne $TT2
10898 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010899 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010900 my $Short1 = $Type1_Pure{"Name"};
10901 my $Short2 = $Type2_Pure{"Name"};
10902
10903 $Short1=~s/\A\Q$TT1\E //ig;
10904 $Short2=~s/\A\Q$TT2\E //ig;
10905
10906 if($Short1 eq $Short2)
10907 {
10908 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
10909 "Target"=>$Type1_Pure{"Name"},
10910 "Type_Name"=>$Type1_Pure{"Name"},
10911 "Old_Value"=>lc($Type1_Pure{"Type"}),
10912 "New_Value"=>lc($Type2_Pure{"Type"}) );
10913 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010914 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010915 %{$Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id}} = %SubProblems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010916 return %SubProblems;
10917 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010918 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010919 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
10920 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
10921 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
10922 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010923 if($Level eq "Binary"
10924 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010925 {
10926 my $ProblemKind = "DataType_Size";
10927 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010928 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010929 {
10930 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
10931 $ProblemKind = "Size_Of_Copying_Class";
10932 }
10933 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
10934 {
10935 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
10936 $ProblemKind = "Size_Of_Allocable_Class_Increased";
10937 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010938 else
10939 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010940 # descreased size of allocable class
10941 # it has no special effects
10942 }
10943 }
10944 }
10945 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
10946 "Target"=>$Type1_Pure{"Name"},
10947 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010948 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
10949 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE,
10950 "InitialType_Type"=>$Type1_Pure{"Type"} );
10951 }
10952 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010953 if(defined $Type1_Pure{"BaseType"}
10954 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010955 { # checking base types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010956 %Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010957 foreach my $Sub_SubProblemType (keys(%Sub_SubProblems))
10958 {
10959 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems{$Sub_SubProblemType}}))
10960 {
10961 foreach my $Attr (keys(%{$Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}})) {
10962 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}{$Attr} = $Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}{$Attr};
10963 }
10964 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}{"InitialType_Type"} = $Type1_Pure{"Type"};
10965 }
10966 }
10967 }
10968 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
10969 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
10970 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
10971 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
10972 { # detect removed and renamed fields
10973 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
10974 next if(not $Member_Name);
10975 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);
10976 if($MemberPair_Pos eq "lost")
10977 {
10978 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
10979 {
10980 if(isUnnamed($Member_Name))
10981 { # support for old-version dumps
10982 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010983 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010984 next;
10985 }
10986 }
10987 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
10988 { # renamed
10989 $RenamedField{$Member_Pos}=$RenamedTo;
10990 $RenamedField_Rev{$NameToPosB{$RenamedTo}}=$Member_Name;
10991 }
10992 else
10993 { # removed
10994 $RemovedField{$Member_Pos}=1;
10995 }
10996 }
10997 elsif($Type1_Pure{"Type"} eq "Enum")
10998 {
10999 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11000 next if($Member_Value1 eq "");
11001 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11002 if($MemberPair_Pos ne "lost")
11003 { # renamed
11004 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11005 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11006 if($MemberPair_Pos_Rev eq "lost")
11007 {
11008 $RenamedField{$Member_Pos}=$RenamedTo;
11009 $RenamedField_Rev{$NameToPosB{$RenamedTo}}=$Member_Name;
11010 }
11011 else {
11012 $RemovedField{$Member_Pos}=1;
11013 }
11014 }
11015 else
11016 { # removed
11017 $RemovedField{$Member_Pos}=1;
11018 }
11019 }
11020 }
11021 else
11022 { # related
11023 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11024 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11025 }
11026 }
11027 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11028 { # detect added fields
11029 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11030 next if(not $Member_Name);
11031 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);
11032 if($MemberPair_Pos eq "lost")
11033 {
11034 if(isUnnamed($Member_Name))
11035 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011036 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011037 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011038 next;
11039 }
11040 }
11041 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11042 {
11043 if(not $RenamedField_Rev{$Member_Pos})
11044 { # added
11045 $AddedField{$Member_Pos}=1;
11046 }
11047 }
11048 }
11049 }
11050 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11051 { # detect moved fields
11052 my (%RelPos, %RelPosName, %AbsPos) = ();
11053 my $Pos = 0;
11054 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11055 { # relative positions in 1st version
11056 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11057 next if(not $Member_Name);
11058 if(not $RemovedField{$Member_Pos})
11059 { # old type without removed fields
11060 $RelPos{1}{$Member_Name}=$Pos;
11061 $RelPosName{1}{$Pos} = $Member_Name;
11062 $AbsPos{1}{$Pos++} = $Member_Pos;
11063 }
11064 }
11065 $Pos = 0;
11066 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11067 { # relative positions in 2nd version
11068 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11069 next if(not $Member_Name);
11070 if(not $AddedField{$Member_Pos})
11071 { # new type without added fields
11072 $RelPos{2}{$Member_Name}=$Pos;
11073 $RelPosName{2}{$Pos} = $Member_Name;
11074 $AbsPos{2}{$Pos++} = $Member_Pos;
11075 }
11076 }
11077 foreach my $Member_Name (keys(%{$RelPos{1}}))
11078 {
11079 my $RPos1 = $RelPos{1}{$Member_Name};
11080 my $AbsPos1 = $NameToPosA{$Member_Name};
11081 my $Member_Name2 = $Member_Name;
11082 if(my $RenamedTo = $RenamedField{$AbsPos1})
11083 { # renamed
11084 $Member_Name2 = $RenamedTo;
11085 }
11086 my $RPos2 = $RelPos{2}{$Member_Name2};
11087 if($RPos2 ne "" and $RPos1 ne $RPos2)
11088 { # different relative positions
11089 my $AbsPos2 = $NameToPosB{$Member_Name2};
11090 if($AbsPos1 ne $AbsPos2)
11091 { # different absolute positions
11092 my $ProblemType = "Moved_Field";
11093 if(not isPublic(\%Type1_Pure, $AbsPos1))
11094 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011095 if($Level eq "Source") {
11096 next;
11097 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011098 $ProblemType = "Moved_Private_Field";
11099 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011100 if($Level eq "Binary"
11101 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011102 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011103 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011104 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011105 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011106 if($MemSize1 ne $MemSize2) {
11107 $ProblemType .= "_And_Size";
11108 }
11109 }
11110 if($ProblemType eq "Moved_Private_Field") {
11111 next;
11112 }
11113 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11114 "Target"=>$Member_Name,
11115 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011116 "Old_Value"=>$RPos1,
11117 "New_Value"=>$RPos2 );
11118 }
11119 }
11120 }
11121 }
11122 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011123 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011124 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11125 next if(not $Member_Name);
11126 if(my $RenamedTo = $RenamedField{$Member_Pos})
11127 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011128 if(defined $Constants{2}{$Member_Name})
11129 {
11130 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11131 { # define OLD NEW
11132 next; # Safe
11133 }
11134 }
11135
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011136 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11137 {
11138 if(isPublic(\%Type1_Pure, $Member_Pos))
11139 {
11140 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11141 "Target"=>$Member_Name,
11142 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011143 "Old_Value"=>$Member_Name,
11144 "New_Value"=>$RenamedTo );
11145 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011146 elsif(isReserved($Member_Name))
11147 {
11148 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11149 "Target"=>$Member_Name,
11150 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011151 "Old_Value"=>$Member_Name,
11152 "New_Value"=>$RenamedTo );
11153 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011154 }
11155 elsif($Type1_Pure{"Type"} eq "Enum")
11156 {
11157 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
11158 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
11159 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011160 "Old_Value"=>$Member_Name,
11161 "New_Value"=>$RenamedTo );
11162 }
11163 }
11164 elsif($RemovedField{$Member_Pos})
11165 { # removed
11166 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11167 {
11168 my $ProblemType = "Removed_Field";
11169 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011170 or isUnnamed($Member_Name))
11171 {
11172 if($Level eq "Source") {
11173 next;
11174 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011175 $ProblemType = "Removed_Private_Field";
11176 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011177 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011178 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011179 {
11180 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
11181 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011182 if(getOffset($MNum-1, \%Type1_Pure, $TypeInfo{1}, getArch(1), $WORD_SIZE{1})!=getOffset($RelatedField{$MNum-1}, \%Type2_Pure, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011183 { # changed offset
11184 $ProblemType .= "_And_Layout";
11185 }
11186 }
11187 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
11188 { # affected size
11189 $ProblemType .= "_And_Size";
11190 }
11191 }
11192 if($ProblemType eq "Removed_Private_Field") {
11193 next;
11194 }
11195 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11196 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011197 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011198 }
11199 elsif($Type2_Pure{"Type"} eq "Union")
11200 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011201 if($Level eq "Binary"
11202 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011203 {
11204 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
11205 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011206 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011207 }
11208 else
11209 {
11210 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
11211 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011212 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011213 }
11214 }
11215 elsif($Type1_Pure{"Type"} eq "Enum")
11216 {
11217 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
11218 "Target"=>$Member_Name,
11219 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011220 "Old_Value"=>$Member_Name );
11221 }
11222 }
11223 else
11224 { # changed
11225 my $MemberPair_Pos = $RelatedField{$Member_Pos};
11226 if($Type1_Pure{"Type"} eq "Enum")
11227 {
11228 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11229 next if($Member_Value1 eq "");
11230 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
11231 next if($Member_Value2 eq "");
11232 if($Member_Value1 ne $Member_Value2)
11233 {
11234 my $ProblemType = "Enum_Member_Value";
11235 if(isLastElem($Member_Pos, \%Type1_Pure)) {
11236 $ProblemType = "Enum_Last_Member_Value";
11237 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011238 if($SkipConstants{1}{$Member_Name}) {
11239 $ProblemType = "Enum_Private_Member_Value";
11240 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011241 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11242 "Target"=>$Member_Name,
11243 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011244 "Old_Value"=>$Member_Value1,
11245 "New_Value"=>$Member_Value2 );
11246 }
11247 }
11248 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11249 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011250 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
11251 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
11252
11253 if($Access1 ne "private"
11254 and $Access2 eq "private")
11255 {
11256 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
11257 "Target"=>$Member_Name,
11258 "Type_Name"=>$Type1_Pure{"Name"});
11259 }
11260 elsif($Access1 ne "protected"
11261 and $Access1 ne "private"
11262 and $Access2 eq "protected")
11263 {
11264 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
11265 "Target"=>$Member_Name,
11266 "Type_Name"=>$Type1_Pure{"Name"});
11267 }
11268
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011269 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
11270 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011271 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011272 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
11273 $SizeV1 = $BSize1;
11274 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011275 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011276 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
11277 $SizeV2 = $BSize2;
11278 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011279 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
11280 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011281 if($Level eq "Binary"
11282 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011283 {
11284 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
11285 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
11286 { # field size change (including anon-structures and unions)
11287 # - same types
11288 # - unnamed types
11289 # - bitfields
11290 my $ProblemType = "Field_Size";
11291 if(not isPublic(\%Type1_Pure, $Member_Pos)
11292 or isUnnamed($Member_Name))
11293 { # should not be accessed by applications, goes to "Low Severity"
11294 # example: "abidata" members in GStreamer types
11295 $ProblemType = "Private_".$ProblemType;
11296 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011297 if(not isMemPadded($Member_Pos, $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011298 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011299 if($Type2_Pure{"Type"} ne "Union"
11300 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011301 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011302 if(getOffset($MNum-1, \%Type1_Pure, $TypeInfo{1}, getArch(1), $WORD_SIZE{1})!=getOffset($RelatedField{$MNum-1}, \%Type2_Pure, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011303 { # changed offset
11304 $ProblemType .= "_And_Layout";
11305 }
11306 }
11307 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
11308 $ProblemType .= "_And_Type_Size";
11309 }
11310 }
11311 if($ProblemType eq "Private_Field_Size")
11312 { # private field size with no effect
11313 $ProblemType = "";
11314 }
11315 if($ProblemType)
11316 { # register a problem
11317 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11318 "Target"=>$Member_Name,
11319 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011320 "Old_Size"=>$SizeV1,
11321 "New_Size"=>$SizeV2);
11322 }
11323 }
11324 }
11325 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
11326 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
11327 { # do NOT check bitfield type changes
11328 next;
11329 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011330 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011331 {
11332 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
11333 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
11334 {
11335 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
11336 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011337 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011338 }
11339 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
11340 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
11341 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011342 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011343 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011344 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011345 }
11346 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011347 %Sub_SubProblems = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011348 foreach my $ProblemType (keys(%Sub_SubProblems))
11349 {
11350 my $Old_Value = $Sub_SubProblems{$ProblemType}{"Old_Value"};
11351 my $New_Value = $Sub_SubProblems{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011352
11353 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011354 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011355 or $ProblemType eq "Field_Type_And_Size"
11356 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011357 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011358 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011359 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011360 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011361 %{$Sub_SubProblems{"Field_Became_Volatile"}} = %{$Sub_SubProblems{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011362 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011363 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
11364 %{$Sub_SubProblems{"Field_Became_Non_Volatile"}} = %{$Sub_SubProblems{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011365 }
11366 }
11367 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
11368 {
11369 if($RA==2) {
11370 %{$Sub_SubProblems{"Field_Added_Const"}} = %{$Sub_SubProblems{$ProblemType}};
11371 }
11372 else {
11373 %{$Sub_SubProblems{"Field_Became_Const"}} = %{$Sub_SubProblems{$ProblemType}};
11374 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011375 }
11376 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
11377 {
11378 if($RR==2) {
11379 %{$Sub_SubProblems{"Field_Removed_Const"}} = %{$Sub_SubProblems{$ProblemType}};
11380 }
11381 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011382 %{$Sub_SubProblems{"Field_Became_Non_Const"}} = %{$Sub_SubProblems{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011383 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011384 }
11385 }
11386 }
11387
11388 if($Level eq "Source")
11389 {
11390 foreach my $ProblemType (keys(%Sub_SubProblems))
11391 {
11392 my $Old_Value = $Sub_SubProblems{$ProblemType}{"Old_Value"};
11393 my $New_Value = $Sub_SubProblems{$ProblemType}{"New_Value"};
11394
11395 if($ProblemType eq "Field_Type")
11396 {
11397 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011398 delete($Sub_SubProblems{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011399 }
11400 }
11401 }
11402 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011403
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011404 foreach my $ProblemType (keys(%Sub_SubProblems))
11405 {
11406 my $ProblemType_Init = $ProblemType;
11407 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011408 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011409 if(not isPublic(\%Type1_Pure, $Member_Pos)
11410 or isUnnamed($Member_Name)) {
11411 $ProblemType = "Private_".$ProblemType;
11412 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011413 if(not isMemPadded($Member_Pos, $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011414 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011415 if($Type2_Pure{"Type"} ne "Union"
11416 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011417 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011418 if(getOffset($MNum-1, \%Type1_Pure, $TypeInfo{1}, getArch(1), $WORD_SIZE{1})!=getOffset($RelatedField{$MNum-1}, \%Type2_Pure, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011419 { # changed offset
11420 $ProblemType .= "_And_Layout";
11421 }
11422 }
11423 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
11424 $ProblemType .= "_And_Type_Size";
11425 }
11426 }
11427 }
11428 else
11429 {
11430 if(not isPublic(\%Type1_Pure, $Member_Pos)
11431 or isUnnamed($Member_Name)) {
11432 next;
11433 }
11434 }
11435 if($ProblemType eq "Private_Field_Type_And_Size")
11436 { # private field change with no effect
11437 next;
11438 }
11439 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11440 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011441 "Type_Name"=>$Type1_Pure{"Name"});
11442
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011443 foreach my $Attr (keys(%{$Sub_SubProblems{$ProblemType_Init}}))
11444 { # other properties
11445 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubProblems{$ProblemType_Init}{$Attr};
11446 }
11447 }
11448 if(not isPublic(\%Type1_Pure, $Member_Pos))
11449 { # do NOT check internal type changes
11450 next;
11451 }
11452 if($MemberType1_Id and $MemberType2_Id)
11453 {# checking member type changes (replace)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011454 %Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011455 foreach my $Sub_SubProblemType (keys(%Sub_SubProblems))
11456 {
11457 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems{$Sub_SubProblemType}}))
11458 {
11459 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
11460 $SubProblems{$Sub_SubProblemType}{$NewLocation}{"IsInTypeInternals"}=1;
11461 foreach my $Attr (keys(%{$Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}})) {
11462 $SubProblems{$Sub_SubProblemType}{$NewLocation}{$Attr} = $Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}{$Attr};
11463 }
11464 if($Sub_SubLocation!~/\-\>/) {
11465 $SubProblems{$Sub_SubProblemType}{$NewLocation}{"Start_Type_Name"} = $MemberType1_Name;
11466 }
11467 }
11468 }
11469 }
11470 }
11471 }
11472 }
11473 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11474 { # checking added members, public and private
11475 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11476 next if(not $Member_Name);
11477 if($AddedField{$Member_Pos})
11478 { # added
11479 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11480 {
11481 my $ProblemType = "Added_Field";
11482 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011483 or isUnnamed($Member_Name))
11484 {
11485 if($Level eq "Source") {
11486 next;
11487 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011488 $ProblemType = "Added_Private_Field";
11489 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011490 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011491 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011492 {
11493 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
11494 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011495 if(getOffset($MNum-1, \%Type2_Pure, $TypeInfo{2}, getArch(2), $WORD_SIZE{2})!=getOffset($RelatedField_Rev{$MNum-1}, \%Type1_Pure, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011496 { # changed offset
11497 $ProblemType .= "_And_Layout";
11498 }
11499 }
11500 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
11501 $ProblemType .= "_And_Size";
11502 }
11503 }
11504 if($ProblemType eq "Added_Private_Field")
11505 { # skip added private fields
11506 next;
11507 }
11508 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11509 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011510 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011511 }
11512 elsif($Type2_Pure{"Type"} eq "Union")
11513 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011514 if($Level eq "Binary"
11515 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011516 {
11517 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
11518 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011519 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011520 }
11521 else
11522 {
11523 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
11524 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011525 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011526 }
11527 }
11528 elsif($Type2_Pure{"Type"} eq "Enum")
11529 {
11530 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
11531 next if($Member_Value eq "");
11532 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
11533 "Target"=>$Member_Name,
11534 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011535 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011536 }
11537 }
11538 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011539 %{$Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id}} = %SubProblems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011540 pop(@RecurTypes);
11541 return %SubProblems;
11542}
11543
11544sub isUnnamed($) {
11545 return $_[0]=~/\Aunnamed\d+\Z/;
11546}
11547
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011548sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011549{
11550 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011551 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
11552 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
11553 $TypeName = uncover_typedefs($TypeName, $LibVersion);
11554 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011555 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011556 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011557 }
11558 return $TypeName;
11559}
11560
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011561sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011562{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011563 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011564 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011565 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
11566 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011567 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011568 return () if(not $TypeInfo{$LibVersion}{$TypeId});
11569 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011570 return () if(not $Type{"Type"});
11571 if($Type{"Type"} ne $Type_Type)
11572 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011573 return () if(not $Type{"BaseType"});
11574 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011575 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011576 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011577 return %Type;
11578}
11579
11580my %TypeSpecAttributes = (
11581 "Const" => 1,
11582 "Volatile" => 1,
11583 "ConstVolatile" => 1,
11584 "Restrict" => 1,
11585 "Typedef" => 1
11586);
11587
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011588sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011589{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011590 my ($TypeId, $Info) = @_;
11591 if(not $TypeId or not $Info
11592 or not $Info->{$TypeId}) {
11593 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011594 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011595 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
11596 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
11597 }
11598 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011599 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011600 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011601 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011602 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011603 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011604 return %Type;
11605}
11606
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011607sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011608{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011609 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011610 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011611 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
11612 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011613 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011614 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
11615 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011616 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
11617 my $PLevel = 0;
11618 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
11619 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011620 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011621 return $PLevel if(not $Type{"BaseType"});
11622 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
11623 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
11624 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011625}
11626
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011627sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011628{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011629 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011630 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011631 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
11632 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011633 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011634 return () if(not $TypeInfo{$LibVersion}{$TypeId});
11635 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011636 return %Type if(not $Type{"BaseType"});
11637 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011638 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011639 return %Type;
11640}
11641
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011642sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011643{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011644 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011645 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011646 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
11647 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011648 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011649 my $Qual = "";
11650 if($Type{"Type"} eq "Pointer") {
11651 $Qual .= "*";
11652 }
11653 elsif($Type{"Type"} eq "Ref") {
11654 $Qual .= "&";
11655 }
11656 elsif($Type{"Type"} eq "ConstVolatile") {
11657 $Qual .= "const volatile";
11658 }
11659 elsif($Type{"Type"} eq "Const"
11660 or $Type{"Type"} eq "Volatile"
11661 or $Type{"Type"} eq "Restrict") {
11662 $Qual .= lc($Type{"Type"});
11663 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011664 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011665 return $BQual.$Qual;
11666}
11667
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011668sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011669{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011670 my ($TypeId, $Info) = @_;
11671 if(not $TypeId or not $Info
11672 or not $Info->{$TypeId}) {
11673 return ();
11674 }
11675 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011676 return %Type if(not $Type{"BaseType"});
11677 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011678 {
11679 if($Info->{$BTid}) {
11680 return %{$Info->{$BTid}};
11681 }
11682 else { # something is going wrong
11683 return ();
11684 }
11685 }
11686 else {
11687 return %Type;
11688 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011689}
11690
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011691sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011692{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011693 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011694 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011695 return () if(not $TypeInfo{$LibVersion}{$TypeId});
11696 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011697}
11698
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040011699sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011700{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011701 my $Symbol = $_[0];
11702 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
11703}
11704
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011705sub isInLineInst($$$) {
11706 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
11707}
11708
11709sub isTemplateInstance($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011710{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011711 my ($Symbol, $SInfo, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011712 if($CheckObjectsOnly)
11713 {
11714 if($Symbol!~/\A(_Z|\?)/) {
11715 return 0;
11716 }
11717 if(my $Signature = $tr_name{$Symbol})
11718 {
11719 if(index($Signature,">")==-1) {
11720 return 0;
11721 }
11722 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
11723 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011724 if(index($ShortName,"<")!=-1
11725 and index($ShortName,">")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011726 return 1;
11727 }
11728 }
11729 }
11730 }
11731 else
11732 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011733 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011734 {
11735 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
11736 {
11737 if(index($ClassName,"<")!=-1) {
11738 return 1;
11739 }
11740 }
11741 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011742 if(my $ShortName = $SInfo->{"ShortName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011743 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011744 if(index($ShortName,"<")!=-1
11745 and index($ShortName,">")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011746 return 1;
11747 }
11748 }
11749 }
11750 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011751}
11752
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011753sub isTemplateSpec($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011754{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011755 my ($Symbol, $SInfo, $LibVersion) = @_;
11756 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011757 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011758 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011759 { # class specialization
11760 return 1;
11761 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011762 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011763 { # method specialization
11764 return 1;
11765 }
11766 }
11767 return 0;
11768}
11769
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011770sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011771{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011772 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040011773 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011774 { # non-public global data
11775 return 0;
11776 }
11777 if($CheckObjectsOnly) {
11778 return 0 if($Symbol=~/\A(_init|_fini)\Z/);
11779 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011780 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011781 { # support for old ABI dumps in --headers-only mode
11782 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
11783 {
11784 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
11785 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011786 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011787 if(not $PType or $PType eq "Unknown") {
11788 return 0;
11789 }
11790 }
11791 }
11792 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011793 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011794 {
11795 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011796 if($SkipSymbols{$LibVersion}{$Symbol})
11797 { # user defined symbols to ignore
11798 return 0;
11799 }
11800 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
11801 if(not $NameSpace and $ClassId)
11802 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011803 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011804 }
11805 if($NameSpace)
11806 { # user defined namespaces to ignore
11807 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
11808 return 0;
11809 }
11810 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
11811 { # nested namespaces
11812 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
11813 return 0;
11814 }
11815 }
11816 }
11817 if(my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
11818 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011819 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011820 { # --skip-headers or <skip_headers> (not <skip_including>)
11821 if($Skip==1) {
11822 return 0;
11823 }
11824 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011825 }
11826 if($SymbolsListPath and not $SymbolsList{$Symbol})
11827 { # user defined symbols
11828 return 0;
11829 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011830 if($SkipSymbolsListPath and $SkipSymbolsList{$Symbol})
11831 { # user defined symbols
11832 return 0;
11833 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011834 if($AppPath and not $SymbolsList_App{$Symbol})
11835 { # user defined symbols (in application)
11836 return 0;
11837 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011838 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
11839 { # non-target symbols
11840 return 0;
11841 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011842 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011843 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011844 if($CheckObjectsOnly)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011845 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011846 if(isTemplateInstance($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011847 return 0;
11848 }
11849 }
11850 else
11851 {
11852 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011853 or isInLineInst($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011854 {
11855 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
11856 { # inline virtual methods
11857 if($Type=~/InlineVirt/) {
11858 return 1;
11859 }
11860 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
11861 if(not $Allocable)
11862 { # check bases
11863 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
11864 {
11865 if(not isCopyingClass($DCId, $LibVersion))
11866 { # exists a derived class without default c-tor
11867 $Allocable=1;
11868 last;
11869 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011870 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011871 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011872 if(not $Allocable) {
11873 return 0;
11874 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011875 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011876 else
11877 { # inline non-virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011878 return 0;
11879 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011880 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011881 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011882 }
11883 }
11884 return 1;
11885}
11886
11887sub mergeImpl()
11888{
11889 my $DiffCmd = get_CmdPath("diff");
11890 if(not $DiffCmd) {
11891 exitStatus("Not_Found", "can't find \"diff\"");
11892 }
11893 foreach my $Interface (sort keys(%{$Symbol_Library{1}}))
11894 { # implementation changes
11895 next if($CompleteSignature{1}{$Interface}{"Private"});
11896 next if(not $CompleteSignature{1}{$Interface}{"Header"} and not $CheckObjectsOnly);
11897 next if(not $Symbol_Library{2}{$Interface} and not $Symbol_Library{2}{$SymVer{2}{$Interface}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011898 if(not symbolFilter($Interface, 1, "Affected", "Binary")) {
11899 next;
11900 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011901 my $Impl1 = canonifyImpl($Interface_Impl{1}{$Interface});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011902 next if(not $Impl1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011903 my $Impl2 = canonifyImpl($Interface_Impl{2}{$Interface});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011904 next if(not $Impl2);
11905 if($Impl1 ne $Impl2)
11906 {
11907 writeFile("$TMP_DIR/impl1", $Impl1);
11908 writeFile("$TMP_DIR/impl2", $Impl2);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040011909 my $Diff = `$DiffCmd -rNau \"$TMP_DIR/impl1\" \"$TMP_DIR/impl2\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011910 $Diff=~s/(---|\+\+\+).+\n//g;
11911 $Diff=~s/[ ]{3,}/ /g;
11912 $Diff=~s/\n\@\@/\n \n\@\@/g;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040011913 unlink("$TMP_DIR/impl1");
11914 unlink("$TMP_DIR/impl2");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011915 %{$CompatProblems_Impl{$Interface}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011916 "Diff" => get_CodeView($Diff) );
11917 }
11918 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011919
11920 # clean memory
11921 %Interface_Impl = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011922}
11923
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011924sub canonifyImpl($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011925{
11926 my $FuncBody= $_[0];
11927 return "" if(not $FuncBody);
11928 $FuncBody=~s/0x[a-f\d]+/0x?/g;# addr
11929 $FuncBody=~s/((\A|\n)[a-z]+[\t ]+)[a-f\d]+([^x]|\Z)/$1?$3/g;# call, jump
11930 $FuncBody=~s/# [a-f\d]+ /# ? /g;# call, jump
11931 $FuncBody=~s/%([a-z]+[a-f\d]*)/\%reg/g;# registers
11932 while($FuncBody=~s/\nnop[ \t]*(\n|\Z)/$1/g){};# empty op
11933 $FuncBody=~s/<.+?\.cpp.+?>/<name.cpp>/g;
11934 $FuncBody=~s/(\A|\n)[a-f\d]+ </$1? </g;# 5e74 <_ZN...
11935 $FuncBody=~s/\.L\d+/.L/g;
11936 $FuncBody=~s/#(-?)\d+/#$1?/g;# r3, [r3, #120]
11937 $FuncBody=~s/[\n]{2,}/\n/g;
11938 return $FuncBody;
11939}
11940
11941sub get_CodeView($)
11942{
11943 my $Code = $_[0];
11944 my $View = "";
11945 foreach my $Line (split(/\n/, $Code))
11946 {
11947 if($Line=~s/\A(\+|-)/$1 /g)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011948 { # bold line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011949 $View .= "<tr><td><b>".htmlSpecChars($Line)."</b></td></tr>\n";
11950 }
11951 else {
11952 $View .= "<tr><td>".htmlSpecChars($Line)."</td></tr>\n";
11953 }
11954 }
11955 return "<table class='code_view'>$View</table>\n";
11956}
11957
11958sub getImplementations($$)
11959{
11960 my ($LibVersion, $Path) = @_;
11961 return if(not $LibVersion or not -e $Path);
11962 if($OSgroup eq "macos")
11963 {
11964 my $OtoolCmd = get_CmdPath("otool");
11965 if(not $OtoolCmd) {
11966 exitStatus("Not_Found", "can't find \"otool\"");
11967 }
11968 my $CurInterface = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040011969 foreach my $Line (split(/\n/, `$OtoolCmd -tv \"$Path\" 2>\"$TMP_DIR/null\"`))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011970 {
11971 if($Line=~/\A\s*_(\w+)\s*:/i) {
11972 $CurInterface = $1;
11973 }
11974 elsif($Line=~/\A\s*[\da-z]+\s+(.+?)\Z/i) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011975 $Interface_Impl{$LibVersion}{$CurInterface} .= $1."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011976 }
11977 }
11978 }
11979 else
11980 {
11981 my $ObjdumpCmd = get_CmdPath("objdump");
11982 if(not $ObjdumpCmd) {
11983 exitStatus("Not_Found", "can't find \"objdump\"");
11984 }
11985 my $CurInterface = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040011986 foreach my $Line (split(/\n/, `$ObjdumpCmd -d \"$Path\" 2>\"$TMP_DIR/null\"`))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011987 {
11988 if($Line=~/\A[\da-z]+\s+<(\w+)>/i) {
11989 $CurInterface = $1;
11990 }
11991 else
11992 { # x86: 51fa:(\t)89 e5 (\t)mov %esp,%ebp
11993 # arm: 5020:(\t)e24cb004(\t)sub(\t)fp, ip, #4(\t); 0x4
11994 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 +040011995 $Interface_Impl{$LibVersion}{$CurInterface} .= $2."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011996 }
11997 }
11998 }
11999 }
12000}
12001
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012002sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012003{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012004 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012005 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12006 {
12007 if(link_symbol($Symbol, 1, "+Deps"))
12008 { # linker can find a new symbol
12009 # in the old-version library
12010 # So, it's not a new symbol
12011 next;
12012 }
12013 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012014 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012015 next;
12016 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012017 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012018 }
12019}
12020
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012021sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012022{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012023 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012024 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12025 {
12026 if($CheckObjectsOnly) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012027 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012028 }
12029 if(link_symbol($Symbol, 2, "+Deps"))
12030 { # linker can find an old symbol
12031 # in the new-version library
12032 next;
12033 }
12034 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012035 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012036 next;
12037 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012038 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012039 }
12040}
12041
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012042sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012043{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012044 my $Level = $_[0];
12045 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012046 { # checking added symbols
12047 next if($CompleteSignature{2}{$Symbol}{"Private"});
12048 next if(not $CompleteSignature{2}{$Symbol}{"Header"} and not $CheckObjectsOnly);
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012049 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012050 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012051 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012052 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012053 { # checking removed symbols
12054 next if($CompleteSignature{1}{$Symbol}{"Private"});
12055 next if(not $CompleteSignature{1}{$Symbol}{"Header"} and not $CheckObjectsOnly);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012056 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012057 { # skip v-tables for templates, that should not be imported by applications
12058 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012059 if(my $CName = $VTableClass{$Symbol})
12060 {
12061 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12062 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012063 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012064 next;
12065 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012066 }
12067 }
12068 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012069 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012070 }
12071 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12072 { # symbols for pure virtual methods cannot be called by clients
12073 next;
12074 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012075 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012076 }
12077}
12078
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012079sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012080{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012081 my ($LibVersion, $V) = @_;
12082 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12083 return $Cache{"checkDump"}{$LibVersion}{$V};
12084 }
12085 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012086}
12087
12088sub detectAdded_H($)
12089{
12090 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012091 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12092 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012093 if($Level eq "Source")
12094 { # remove symbol version
12095 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12096 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012097
12098 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12099 { # skip artificial constructors
12100 next;
12101 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012102 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012103 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12104 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012105 next;
12106 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012107 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012108 next;
12109 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012110 if(not defined $CompleteSignature{1}{$Symbol}
12111 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12112 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012113 if($UsedDump{2}{"SrcBin"})
12114 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012115 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012116 { # support for old and different (!) ABI dumps
12117 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12118 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012119 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012120 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012121 {
12122 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12123 {
12124 if($Lang eq "C")
12125 { # support for old ABI dumps: missed extern "C" functions
12126 next;
12127 }
12128 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012129 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012130 else
12131 {
12132 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012133 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012134 next;
12135 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012136 }
12137 }
12138 }
12139 }
12140 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012141 }
12142 }
12143}
12144
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012145sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012146{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012147 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012148 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12149 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012150 if($Level eq "Source")
12151 { # remove symbol version
12152 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12153 $Symbol=$SN;
12154 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012155 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12156 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012157 next;
12158 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012159 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012160 next;
12161 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012162 if(not defined $CompleteSignature{2}{$Symbol}
12163 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012164 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012165 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012166 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012167 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012168 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012169 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
12170 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012171 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012172 if($CheckHeadersOnly)
12173 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012174 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
12175 {
12176 if($Lang eq "C")
12177 { # support for old ABI dumps: missed extern "C" functions
12178 next;
12179 }
12180 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012181 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012182 else
12183 {
12184 if(not link_symbol($Symbol, 1, "-Deps"))
12185 { # skip removed inline symbols
12186 next;
12187 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012188 }
12189 }
12190 }
12191 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012192 if(not checkDump(1, "2.15"))
12193 {
12194 if($Symbol=~/_IT_E\Z/)
12195 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
12196 next;
12197 }
12198 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012199 if(not $CompleteSignature{1}{$Symbol}{"Class"})
12200 {
12201 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
12202 {
12203 if(defined $Constants{2}{$Short})
12204 {
12205 my $Val = $Constants{2}{$Short}{"Value"};
12206 if(defined $Func_ShortName{2}{$Val})
12207 { # old name defined to new
12208 next;
12209 }
12210 }
12211 }
12212
12213 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012214 $RemovedInt{$Level}{$Symbol} = 1;
12215 if($Level eq "Source")
12216 { # search for a source-compatible equivalent
12217 setAlternative($Symbol, $Level);
12218 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012219 }
12220 }
12221}
12222
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012223sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012224{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012225 my $Level = $_[0];
12226 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012227 { # checking added symbols
12228 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012229 next if($CompleteSignature{2}{$Symbol}{"Private"});
12230 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012231 if($Level eq "Binary")
12232 {
12233 if($CompleteSignature{2}{$Symbol}{"InLine"})
12234 {
12235 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
12236 { # skip inline non-virtual functions
12237 next;
12238 }
12239 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012240 }
12241 else
12242 { # Source
12243 if($SourceAlternative_B{$Symbol}) {
12244 next;
12245 }
12246 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012247 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012248 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012249 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012250 { # checking removed symbols
12251 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012252 next if($CompleteSignature{1}{$Symbol}{"Private"});
12253 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012254 if($Level eq "Binary")
12255 {
12256 if($CompleteSignature{1}{$Symbol}{"InLine"})
12257 {
12258 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
12259 { # skip inline non-virtual functions
12260 next;
12261 }
12262 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012263 }
12264 else
12265 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012266 if(my $Alt = $SourceAlternative{$Symbol})
12267 {
12268 if(defined $CompleteSignature{1}{$Alt}
12269 and $CompleteSignature{1}{$Symbol}{"Const"})
12270 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012271 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012272 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012273 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012274 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012275 }
12276 else
12277 { # do NOT show removed symbol
12278 next;
12279 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012280 }
12281 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012282 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012283 }
12284}
12285
12286sub addParamNames($)
12287{
12288 my $LibraryVersion = $_[0];
12289 return if(not keys(%AddIntParams));
12290 my $SecondVersion = $LibraryVersion==1?2:1;
12291 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
12292 {
12293 next if(not keys(%{$AddIntParams{$Interface}}));
12294 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012295 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012296 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
12297 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012298 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012299 if(defined $CompleteSignature{$SecondVersion}{$Interface}
12300 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
12301 {
12302 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
12303 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
12304 }
12305 }
12306 else {
12307 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
12308 }
12309 }
12310 }
12311 }
12312}
12313
12314sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012315{ # detect changed typedefs to show
12316 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012317 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
12318 {
12319 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012320 my $BName1 = $Typedef_BaseName{1}{$Typedef};
12321 if(not $BName1 or isAnon($BName1)) {
12322 next;
12323 }
12324 my $BName2 = $Typedef_BaseName{2}{$Typedef};
12325 if(not $BName2 or isAnon($BName2)) {
12326 next;
12327 }
12328 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012329 $ChangedTypedef{$Typedef} = 1;
12330 }
12331 }
12332}
12333
12334sub get_symbol_suffix($$)
12335{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012336 my ($Symbol, $Full) = @_;
12337 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040012338 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012339 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012340 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012341 if(not $Full) {
12342 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
12343 }
12344 return $Suffix;
12345}
12346
12347sub get_symbol_prefix($$)
12348{
12349 my ($Symbol, $LibVersion) = @_;
12350 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
12351 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
12352 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012353 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012354 }
12355 return $ShortName;
12356}
12357
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012358sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012359{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012360 my $Symbol = $_[0];
12361 my $PSymbol = $Symbol;
12362 if(not defined $CompleteSignature{2}{$PSymbol}
12363 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
12364 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
12365 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012366 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012367 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012368 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012369 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012370 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
12371 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012372 {
12373 if(defined $CompleteSignature{2}{$PSymbol}
12374 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
12375 {
12376 $SourceAlternative{$Symbol} = $PSymbol;
12377 $SourceAlternative_B{$PSymbol} = $Symbol;
12378 if(not defined $CompleteSignature{1}{$PSymbol}
12379 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
12380 $SourceReplacement{$Symbol} = $PSymbol;
12381 }
12382 }
12383 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012384 }
12385 else
12386 {
12387 foreach my $Sp ("KV", "VK", "K", "V")
12388 {
12389 if($PSymbol=~s/\A_ZN$Sp/_ZN/
12390 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
12391 {
12392 if(defined $CompleteSignature{2}{$PSymbol}
12393 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
12394 {
12395 $SourceAlternative{$Symbol} = $PSymbol;
12396 $SourceAlternative_B{$PSymbol} = $Symbol;
12397 if(not defined $CompleteSignature{1}{$PSymbol}
12398 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
12399 $SourceReplacement{$Symbol} = $PSymbol;
12400 }
12401 }
12402 }
12403 $PSymbol = $Symbol;
12404 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012405 }
12406 }
12407 }
12408 return "";
12409}
12410
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012411sub getSymKind($$)
12412{
12413 my ($Symbol, $LibVersion) = @_;
12414 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
12415 {
12416 return "Global_Data";
12417 }
12418 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
12419 {
12420 return "Method";
12421 }
12422 return "Function";
12423}
12424
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040012425sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012426{
12427 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012428 my %SubProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012429
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012430 mergeBases($Level);
12431
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012432 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012433 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012434 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012435 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012436 next;
12437 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012438 if(defined $CompleteSignature{1}{$Symbol}
12439 and $CompleteSignature{1}{$Symbol}{"Header"})
12440 { # double-check added symbol
12441 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012442 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012443 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012444 next;
12445 }
12446 if($Symbol=~/\A(_Z|\?)/)
12447 { # C++
12448 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
12449 }
12450 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
12451 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012452 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
12453 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012454 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012455 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012456 {
12457 if($TName_Tid{1}{$AffectedClass_Name})
12458 { # class should exist in previous version
12459 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
12460 { # old v-table is NOT copied by old applications
12461 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
12462 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012463 "Target"=>get_Signature($Symbol, 2),
12464 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012465 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012466 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012467 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012468 }
12469 }
12470 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012471 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
12472 { # check all removed exported symbols
12473 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012474 next;
12475 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012476 if(defined $CompleteSignature{2}{$Symbol}
12477 and $CompleteSignature{2}{$Symbol}{"Header"})
12478 { # double-check removed symbol
12479 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012480 }
12481 if($CompleteSignature{1}{$Symbol}{"Private"})
12482 { # skip private methods
12483 next;
12484 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012485 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012486 next;
12487 }
12488 $CheckedSymbols{$Level}{$Symbol} = 1;
12489 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
12490 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012491 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
12492 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012493 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012494 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
12495 {
12496 if($TName_Tid{2}{$AffectedClass_Name})
12497 { # class should exist in newer version
12498 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
12499 { # old v-table is NOT copied by old applications
12500 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
12501 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012502 "Target"=>get_Signature($OverriddenMethod, 1),
12503 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012504 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012505 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012506 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012507 }
12508 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012509 if($Level eq "Binary"
12510 and $OSgroup eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012511 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012512 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012513 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012514 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012515 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012516 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012517 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012518 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012519 {
12520 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
12521 "Target"=>$tr_name{$Symbol},
12522 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012523 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012524 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012525 else
12526 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012527 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012528 "Target"=>$tr_name{$Symbol},
12529 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012530 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012531 }
12532 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012533 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012534 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012535 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012536 {
12537 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
12538 "Target"=>$tr_name{$Symbol},
12539 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012540 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012541 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012542 else
12543 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012544 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012545 "Target"=>$tr_name{$Symbol},
12546 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012547 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012548 }
12549 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012550 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
12551 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
12552 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
12553 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
12554 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012555 {
12556 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012557 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012558 $ProblemType = "Global_Data_Symbol_Changed_Type";
12559 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012560 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
12561 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012562 "Old_Type"=>$RTName1,
12563 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012564 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012565 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012566 }
12567 }
12568 }
12569 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012570 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012571 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012572 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012573 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012574 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012575 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012576 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012577 if($CompleteSignature{1}{$Symbol}{"Constructor"})
12578 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012579 if($Symbol=~/(C1E|C2E)/)
12580 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012581 my $CtorType = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012582 $NewSym=~s/(C1E|C2E)/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012583 }
12584 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012585 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
12586 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012587 if($Symbol=~/(D0E|D1E|D2E)/)
12588 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012589 my $DtorType = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012590 $NewSym=~s/(D0E|D1E|D2E)/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012591 }
12592 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012593 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012594 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012595 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012596 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012597 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012598 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012599 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012600 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012601 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012602 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012603 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012604 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012605 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012606 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012607 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012608 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012609 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012610 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012611 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012612 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012613 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012614 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012615 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012616 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012617 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012618 { # "volatile" to non-"volatile"
12619
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012620 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012621 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012622 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012623 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012624 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012625 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012626 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012627 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012628 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012629 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012630 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012631 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012632 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012633 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012634 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012635 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012636 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012637 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
12638 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012639 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012640 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012641 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012642 }
12643 }
12644 }
12645 }
12646 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012647 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12648 { # checking symbols
12649 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12650 if($Level eq "Source")
12651 { # remove symbol version
12652 $Symbol=$SN;
12653 }
12654 else
12655 { # Binary
12656 if(not $SV)
12657 { # symbol without version
12658 if(my $VSym = $SymVer{1}{$Symbol})
12659 { # the symbol is linked with versioned symbol
12660 if($CompleteSignature{2}{$VSym}{"MnglName"})
12661 { # show report for symbol@ver only
12662 next;
12663 }
12664 elsif(not link_symbol($VSym, 2, "-Deps"))
12665 { # changed version: sym@v1 to sym@v2
12666 # do NOT show report for symbol
12667 next;
12668 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012669 }
12670 }
12671 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012672 my $PSymbol = $Symbol;
12673 if($Level eq "Source"
12674 and my $S = $SourceReplacement{$Symbol})
12675 { # take a source-compatible replacement function
12676 $PSymbol = $S;
12677 }
12678 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012679 { # private symbols
12680 next;
12681 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012682 if(not defined $CompleteSignature{1}{$Symbol}
12683 or not defined $CompleteSignature{2}{$PSymbol})
12684 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012685 next;
12686 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012687 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
12688 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
12689 { # no mangled name
12690 next;
12691 }
12692 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12693 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012694 { # without a header
12695 next;
12696 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012697
12698 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
12699 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
12700 { # became pure
12701 next;
12702 }
12703 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
12704 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
12705 { # became non-pure
12706 next;
12707 }
12708
12709 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
12710 { # exported, target, inline virtual and pure virtual
12711 next;
12712 }
12713 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
12714 { # exported, target, inline virtual and pure virtual
12715 next;
12716 }
12717
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012718 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012719 {
12720 if($CompleteSignature{1}{$Symbol}{"Data"}
12721 and $CompleteSignature{2}{$PSymbol}{"Data"})
12722 {
12723 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
12724 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
12725 if(defined $Value1)
12726 {
12727 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
12728 if(defined $Value2)
12729 {
12730 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
12731 if($Value1 ne $Value2)
12732 {
12733 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
12734 "Old_Value"=>$Value1,
12735 "New_Value"=>$Value2,
12736 "Target"=>get_Signature($Symbol, 1) );
12737 }
12738 }
12739 }
12740 }
12741 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012742
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012743 if($CompleteSignature{2}{$PSymbol}{"Private"})
12744 {
12745 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
12746 "Target"=>get_Signature_M($PSymbol, 2) );
12747 }
12748 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
12749 and $CompleteSignature{2}{$PSymbol}{"Protected"})
12750 {
12751 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
12752 "Target"=>get_Signature_M($PSymbol, 2) );
12753 }
12754 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
12755 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
12756 {
12757 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
12758 "Target"=>get_Signature_M($PSymbol, 2) );
12759 }
12760
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012761 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012762 mergeVirtualTables($Symbol, $Level);
12763
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012764 if($COMPILE_ERRORS)
12765 { # if some errors occurred at the compiling stage
12766 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012767 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012768 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012769 { # missed information about parameters in newer version
12770 next;
12771 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012772 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012773 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012774 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012775 next;
12776 }
12777 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012778 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012779 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012780 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012781 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
12782 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012783 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
12784 "Target"=>get_Signature($Symbol, 1)
12785 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012786 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012787 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012788 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
12789 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012790 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012791 "Target"=>get_Signature($Symbol, 1)
12792 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012793 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012794 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
12795 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012796 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012797 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012798 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012799 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
12800 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
12801 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012802 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012803 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012804 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
12805 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012806 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012807 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012808 my $ProblemType = "Virtual_Method_Position";
12809 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
12810 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012811 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012812 if(isUsedClass($Class_Id, 1, $Level))
12813 {
12814 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012815 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012816 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012817 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
12818 next;
12819 }
12820 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012821 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012822 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
12823 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012824 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012825 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012826 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012827 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012828 }
12829 }
12830 }
12831 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012832 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
12833 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012834 { # do NOT check type changes in pure virtuals
12835 next;
12836 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012837 $CheckedSymbols{$Level}{$Symbol}=1;
12838 if($Symbol=~/\A(_Z|\?)/
12839 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012840 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012841 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012842 { # checking parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012843 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012844 }
12845 }
12846 else
12847 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012848 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012849 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012850 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012851 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
12852 last if($PType2_Name eq "...");
12853 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
12854 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012855 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012856 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012857 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012858 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
12859 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012860 if($#Positions1==-1 or $#Positions2>$#Positions1) {
12861 $ParamPos_Prev = "lost";
12862 }
12863 }
12864 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012865 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012866 }
12867 if($ParamPos_Prev eq "lost")
12868 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012869 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012870 {
12871 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012872 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012873 $ProblemType = "Added_Unnamed_Parameter";
12874 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012875 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012876 "Target"=>$PName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012877 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012878 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012879 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012880 }
12881 else
12882 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012883 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012884 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012885 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012886 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
12887 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012888 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012889 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012890 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012891 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012892 "Target"=>$PName_Old,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012893 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012894 "Param_Type"=>$PType2_Name,
12895 "Old_Value"=>$PName_Old,
12896 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012897 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012898 }
12899 }
12900 else
12901 {
12902 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012903 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012904 $ProblemType = "Added_Middle_Unnamed_Parameter";
12905 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012906 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012907 "Target"=>$PName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012908 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012909 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012910 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012911 }
12912 }
12913 }
12914 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012915 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012916 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012917 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012918 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012919 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012920 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012921 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012922 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012923 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012924 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
12925 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012926 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012927 }
12928 }
12929 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012930 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012931 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012932 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012933 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
12934 last if($PType1_Name eq "...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012935 my $Parameter_Name = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
12936 my $Parameter_NewName = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012937 my $ParamPos_New = "-1";
12938 if($Parameter_Name=~/\Ap\d+\Z/i)
12939 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012940 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
12941 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012942 if($#Positions2==-1 or $#Positions2<$#Positions1) {
12943 $ParamPos_New = "lost";
12944 }
12945 }
12946 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012947 $ParamPos_New = find_ParamPair_Pos_byName($Parameter_Name, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012948 }
12949 if($ParamPos_New eq "lost")
12950 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012951 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012952 {
12953 my $ProblemType = "Removed_Parameter";
12954 if($Parameter_Name=~/\Ap\d+\Z/) {
12955 $ProblemType = "Removed_Unnamed_Parameter";
12956 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012957 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012958 "Target"=>$Parameter_Name,
12959 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012960 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012961 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012962 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012963 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012964 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012965 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012966 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012967 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012968 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012969 and find_ParamPair_Pos_byName($Parameter_NewName, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012970 {
12971 if($Parameter_NewName!~/\Ap\d+\Z/ and $Parameter_Name!~/\Ap\d+\Z/)
12972 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012973 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012974 "Target"=>$Parameter_Name,
12975 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012976 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012977 "Old_Value"=>$Parameter_Name,
12978 "New_Value"=>$Parameter_NewName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012979 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012980 }
12981 }
12982 else
12983 {
12984 my $ProblemType = "Removed_Middle_Parameter";
12985 if($Parameter_Name=~/\Ap\d+\Z/) {
12986 $ProblemType = "Removed_Middle_Unnamed_Parameter";
12987 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012988 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012989 "Target"=>$Parameter_Name,
12990 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012991 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012992 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012993 }
12994 }
12995 }
12996 }
12997 }
12998 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012999 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13000 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
13001 %SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013002
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013003 foreach my $SubProblemType (keys(%SubProblems))
13004 {
13005 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
13006 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013007 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013008
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013009 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013010 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013011 if($SubProblemType eq "Return_Type_And_Size") {
13012 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13013 }
13014 elsif($SubProblemType eq "Return_Type_Format") {
13015 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13016 }
13017 else {
13018 $ProblemTypes{"Global_Data_Type"} = 1;
13019 }
13020
13021 # quals
13022 if($SubProblemType eq "Return_Type"
13023 or $SubProblemType eq "Return_Type_And_Size"
13024 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013025 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013026 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13027 { # const to non-const
13028 if($RR==2) {
13029 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13030 }
13031 else {
13032 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13033 }
13034 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013035 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013036 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13037 { # non-const to const
13038 if($RA==2) {
13039 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13040 }
13041 else {
13042 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13043 }
13044 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013045 }
13046 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013047 }
13048 else
13049 {
13050 # quals
13051 if($SubProblemType eq "Return_Type"
13052 or $SubProblemType eq "Return_Type_And_Size"
13053 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013054 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013055 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013056 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013057 if(addedQual($Old_Value, $New_Value, "volatile"))
13058 {
13059 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13060 if($Level ne "Source"
13061 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13062 $ProblemTypes{"Return_Type"} = 1;
13063 }
13064 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013065 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013066 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13067 {
13068 if($RA==2) {
13069 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13070 }
13071 else {
13072 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13073 }
13074 if($Level ne "Source"
13075 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13076 $ProblemTypes{"Return_Type"} = 1;
13077 }
13078 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013079 }
13080 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013081 if($Level eq "Binary"
13082 and not $CompleteSignature{1}{$Symbol}{"Data"})
13083 {
13084 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13085 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13086 { # if one of the architectures is unknown
13087 # then set other arhitecture to unknown too
13088 ($Arch1, $Arch2) = ("unknown", "unknown");
13089 }
13090 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013091 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013092 {
13093 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13094 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13095 }
13096 else
13097 {
13098 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13099 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13100 }
13101
13102 if($SubProblemType eq "Return_Type_Became_Void")
13103 {
13104 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13105 { # parameters stack has been affected
13106 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013107 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013108 }
13109 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013110 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013111 }
13112 }
13113 }
13114 elsif($SubProblemType eq "Return_Type_From_Void")
13115 {
13116 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13117 { # parameters stack has been affected
13118 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013119 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013120 }
13121 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013122 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013123 }
13124 }
13125 }
13126 elsif($SubProblemType eq "Return_Type"
13127 or $SubProblemType eq "Return_Type_And_Size"
13128 or $SubProblemType eq "Return_Type_Format")
13129 {
13130 if($Conv1{"Method"} ne $Conv2{"Method"})
13131 {
13132 if($Conv1{"Method"} eq "stack")
13133 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013134 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013135 }
13136 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013137 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013138 }
13139 }
13140 else
13141 {
13142 if($Conv1{"Method"} eq "reg")
13143 {
13144 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13145 {
13146 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013147 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013148 }
13149 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013150 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013151 }
13152 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013153 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013154 }
13155 }
13156 }
13157 }
13158 }
13159 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013160
13161 if(not keys(%ProblemTypes))
13162 { # default
13163 $ProblemTypes{$SubProblemType} = 1;
13164 }
13165
13166 foreach my $ProblemType (keys(%ProblemTypes))
13167 { # additional
13168 @{$CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013169 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013170 }
13171 if($ReturnType1_Id and $ReturnType2_Id)
13172 {
13173 @RecurTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013174 %SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013175
13176 if($CompleteSignature{1}{$Symbol}{"Data"})
13177 {
13178 if($Level eq "Binary")
13179 {
13180 if(get_PLevel($ReturnType1_Id, 1)==0)
13181 {
13182 foreach my $SubProblemType (keys(%SubProblems))
13183 { # add "Global_Data_Size" problem
13184 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
13185 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
13186 if($SubProblemType eq "DataType_Size")
13187 { # add a new problem
13188 %{$SubProblems{"Global_Data_Size"}} = %{$SubProblems{$SubProblemType}};
13189 }
13190 }
13191 }
13192 if(not defined $SubProblems{"Global_Data_Size"})
13193 {
13194 if(defined $GlobalDataObject{1}{$Symbol}
13195 and defined $GlobalDataObject{2}{$Symbol})
13196 {
13197 my $Old_Size = $GlobalDataObject{1}{$Symbol};
13198 my $New_Size = $GlobalDataObject{2}{$Symbol};
13199 if($Old_Size!=$New_Size)
13200 {
13201 %{$SubProblems{"Global_Data_Size"}{"retval"}} = (
13202 "Old_Size"=>$Old_Size*$BYTE_SIZE,
13203 "New_Size"=>$New_Size*$BYTE_SIZE );
13204 }
13205 }
13206 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013207 }
13208 }
13209 foreach my $SubProblemType (keys(%SubProblems))
13210 {
13211 foreach my $SubLocation (keys(%{$SubProblems{$SubProblemType}}))
13212 {
13213 my $NewLocation = ($SubLocation)?"retval->".$SubLocation:"retval";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013214 %{$CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013215 "Return_Type_Name"=>$TypeInfo{1}{$ReturnType1_Id}{"Name"} );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013216 @{$CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}}{keys(%{$SubProblems{$SubProblemType}{$SubLocation}})} = values %{$SubProblems{$SubProblemType}{$SubLocation}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013217 if($SubLocation!~/\-\>/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013218 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}{"Start_Type_Name"} = $TypeInfo{1}{$ReturnType1_Id}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013219 }
13220 }
13221 }
13222 }
13223
13224 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013225 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
13226 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
13227 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013228 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013229 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013230 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
13231 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013232 if($ThisPtr1_Id and $ThisPtr2_Id)
13233 {
13234 @RecurTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013235 %SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013236 foreach my $SubProblemType (keys(%SubProblems))
13237 {
13238 foreach my $SubLocation (keys(%{$SubProblems{$SubProblemType}}))
13239 {
13240 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013241 %{$CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013242 "Object_Type_Name"=>$TypeInfo{1}{$ObjTId1}{"Name"} );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013243 @{$CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}}{keys(%{$SubProblems{$SubProblemType}{$SubLocation}})} = values %{$SubProblems{$SubProblemType}{$SubLocation}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013244 if($SubLocation!~/\-\>/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013245 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}{"Start_Type_Name"} = $TypeInfo{1}{$ObjTId1}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013246 }
13247 }
13248 }
13249 }
13250 }
13251 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013252 if($Level eq "Binary") {
13253 mergeVTables($Level);
13254 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013255 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
13256 $CheckedSymbols{$Level}{$Symbol} = 1;
13257 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013258}
13259
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013260sub rmQuals($$)
13261{
13262 my ($Value, $Qual) = @_;
13263 if(not $Qual) {
13264 return $Value;
13265 }
13266 if($Qual eq "all")
13267 { # all quals
13268 $Qual = "const|volatile|restrict";
13269 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013270 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013271 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013272 }
13273 return $Value;
13274}
13275
13276sub cmpBTypes($$$$)
13277{
13278 my ($T1, $T2, $V1, $V2) = @_;
13279 $T1 = uncover_typedefs($T1, $V1);
13280 $T2 = uncover_typedefs($T2, $V2);
13281 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
13282}
13283
13284sub addedQual($$$)
13285{
13286 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013287 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013288}
13289
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013290sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013291{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013292 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013293 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013294}
13295
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013296sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013297{
13298 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
13299 $Old_Value = uncover_typedefs($Old_Value, $V1);
13300 $New_Value = uncover_typedefs($New_Value, $V2);
13301 if($Old_Value eq $New_Value)
13302 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013303 return 0;
13304 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013305 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013306 { # without a qual
13307 return 0;
13308 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013309 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013310 { # became non-qual
13311 return 1;
13312 }
13313 else
13314 {
13315 my @BQ1 = getQualModel($Old_Value, $Qual);
13316 my @BQ2 = getQualModel($New_Value, $Qual);
13317 foreach (0 .. $#BQ1)
13318 { # removed qual
13319 if($BQ1[$_]==1
13320 and $BQ2[$_]!=1)
13321 {
13322 return 2;
13323 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013324 }
13325 }
13326 return 0;
13327}
13328
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013329sub getQualModel($$)
13330{
13331 my ($Value, $Qual) = @_;
13332 if(not $Qual) {
13333 return $Value;
13334 }
13335
13336 # cleaning
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013337 while($Value=~/(\w+)/ and $1 ne $Qual) {
13338 $Value=~s/\b$1\b//g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013339 }
13340 $Value=~s/[^\*\&\w]+//g;
13341
13342 # modeling
13343 # int*const*const == 011
13344 # int**const == 001
13345 my @Model = ();
13346 my @Elems = split(/[\*\&]/, $Value);
13347 if(not @Elems) {
13348 return (0);
13349 }
13350 foreach (@Elems)
13351 {
13352 if($_ eq $Qual) {
13353 push(@Model, 1);
13354 }
13355 else {
13356 push(@Model, 0);
13357 }
13358 }
13359
13360 return @Model;
13361}
13362
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013363my %StringTypes = map {$_=>1} (
13364 "char*",
13365 "char const*"
13366);
13367
13368my %CharTypes = map {$_=>1} (
13369 "char",
13370 "char const"
13371);
13372
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013373sub showVal($$$)
13374{
13375 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013376 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040013377 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040013378 if(substr($Value, 0, 2) eq "_Z")
13379 {
13380 if(my $Unmangled = $tr_name{$Value}) {
13381 return $Unmangled;
13382 }
13383 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013384 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013385 { # strings
13386 return "\"$Value\"";
13387 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013388 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013389 { # characters
13390 return "\'$Value\'";
13391 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013392 if($Value eq "")
13393 { # other
13394 return "\'\'";
13395 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013396 return $Value;
13397}
13398
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013399sub getRegs($$$)
13400{
13401 my ($LibVersion, $Symbol, $Pos) = @_;
13402
13403 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
13404 {
13405 my $PName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"};
13406 my %Regs = ();
13407 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
13408 {
13409 if($Elem=~/\A$PName([\.\+]|\Z)/) {
13410 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
13411 }
13412 }
13413
13414 return join(", ", sort keys(%Regs));
13415 }
13416
13417 return undef;
13418}
13419
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013420sub mergeParameters($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013421{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013422 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013423 if(not $Symbol) {
13424 return;
13425 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013426 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
13427 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
13428 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
13429 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013430 if(not $PType1_Id
13431 or not $PType2_Id) {
13432 return;
13433 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013434 my %Type1 = get_Type($PType1_Id, 1);
13435 my %Type2 = get_Type($PType2_Id, 2);
13436 my %BaseType1 = get_BaseType($PType1_Id, 1);
13437 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013438 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013439 if($Level eq "Binary")
13440 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013441 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013442 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
13443 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
13444 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
13445 {
13446 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013447 "Target"=>$PName1,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013448 "Param_Pos"=>$ParamPos1 );
13449 }
13450 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
13451 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
13452 {
13453 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013454 "Target"=>$PName1,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013455 "Param_Pos"=>$ParamPos1 );
13456 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013457 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013458
13459 if(defined $UsedDump{1}{"DWARF"}
13460 and defined $UsedDump{2}{"DWARF"})
13461 {
13462 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
13463 {
13464 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
13465 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
13466 if($Old_Regs and $New_Regs)
13467 {
13468 if($Old_Regs ne $New_Regs)
13469 {
13470 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
13471 "Target"=>$PName1,
13472 "Param_Pos"=>$ParamPos1,
13473 "Old_Value"=>$Old_Regs,
13474 "New_Value"=>$New_Regs );
13475 }
13476 }
13477 elsif($Old_Regs and not $New_Regs)
13478 {
13479 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
13480 "Target"=>$PName1,
13481 "Param_Pos"=>$ParamPos1,
13482 "Old_Value"=>$Old_Regs );
13483 }
13484 elsif(not $Old_Regs and $New_Regs)
13485 {
13486 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
13487 "Target"=>$PName1,
13488 "Param_Pos"=>$ParamPos1,
13489 "New_Value"=>$New_Regs );
13490 }
13491 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
13492 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
13493 {
13494 if($Old_Offset ne $New_Offset)
13495 {
13496 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
13497 "Target"=>$PName1,
13498 "Param_Pos"=>$ParamPos1,
13499 "Old_Value"=>$Old_Offset,
13500 "New_Value"=>$New_Offset );
13501 }
13502 }
13503 }
13504 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013505 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013506 if(checkDump(1, "2.0") and checkDump(2, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013507 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013508 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
13509 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013510 if(not checkDump(1, "2.13")
13511 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013512 { # support for old ABI dumps
13513 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013514 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013515 if($Type1{"Name"} eq "bool"
13516 and $Value_Old eq "false" and $Value_New eq "0")
13517 { # int class::method ( bool p = 0 );
13518 # old ABI dumps: "false"
13519 # new ABI dumps: "0"
13520 $Value_Old = "0";
13521 }
13522 }
13523 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040013524 if(not checkDump(1, "2.18")
13525 and checkDump(2, "2.18"))
13526 { # support for old ABI dumps
13527 if(not defined $Value_Old
13528 and substr($Value_New, 0, 2) eq "_Z") {
13529 $Value_Old = $Value_New;
13530 }
13531 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013532 if(defined $Value_Old)
13533 {
13534 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
13535 if(defined $Value_New)
13536 {
13537 $Value_New = showVal($Value_New, $PType2_Id, 2);
13538 if($Value_Old ne $Value_New)
13539 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013540 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013541 "Target"=>$PName1,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013542 "Param_Pos"=>$ParamPos1,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013543 "Old_Value"=>$Value_Old,
13544 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013545 }
13546 }
13547 else
13548 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013549 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013550 "Target"=>$PName1,
13551 "Param_Pos"=>$ParamPos1,
13552 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013553 }
13554 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013555 elsif(defined $Value_New)
13556 {
13557 $Value_New = showVal($Value_New, $PType2_Id, 2);
13558 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
13559 "Target"=>$PName1,
13560 "Param_Pos"=>$ParamPos1,
13561 "New_Value"=>$Value_New );
13562 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013563 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013564 if($PName1 and $PName2 and $PName1 ne $PName2
13565 and $PType1_Id!=-1 and $PType2_Id!=-1
13566 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013567 { # except unnamed "..." value list (Id=-1)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013568 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013569 "Target"=>$PName1,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013570 "Param_Pos"=>$ParamPos1,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013571 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013572 "Old_Value"=>$PName1,
13573 "New_Value"=>$PName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013574 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013575 }
13576 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013577 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013578 foreach my $SubProblemType (keys(%SubProblems))
13579 { # add new problems, remove false alarms
13580 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
13581 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013582
13583 # quals
13584 if($SubProblemType eq "Parameter_Type"
13585 or $SubProblemType eq "Parameter_Type_And_Size"
13586 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013587 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013588 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013589 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013590 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013591 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013592 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013593 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
13594 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
13595 }
13596 }
13597 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
13598 {
13599 if(removedQual($Old_Value, $New_Value, "volatile")) {
13600 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013601 }
13602 }
13603 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
13604 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
13605 { # int to "int const"
13606 delete($SubProblems{$SubProblemType});
13607 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013608 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013609 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
13610 { # "int const" to int
13611 delete($SubProblems{$SubProblemType});
13612 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013613 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
13614 { # "const" to non-"const"
13615 if($RR==2) {
13616 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
13617 }
13618 else {
13619 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
13620 }
13621 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013622 }
13623 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013624
13625 if($Level eq "Source")
13626 {
13627 foreach my $SubProblemType (keys(%SubProblems))
13628 {
13629 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
13630 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
13631
13632 if($SubProblemType eq "Parameter_Type")
13633 {
13634 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13635 delete($SubProblems{$SubProblemType});
13636 }
13637 }
13638 }
13639 }
13640
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013641 foreach my $SubProblemType (keys(%SubProblems))
13642 { # modify/register problems
13643 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
13644 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013645 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
13646 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013647
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013648 my $NewProblemType = $SubProblemType;
13649 if($Old_Value eq "..." and $New_Value ne "...")
13650 { # change from "..." to "int"
13651 if($ParamPos1==0)
13652 { # ISO C requires a named argument before "..."
13653 next;
13654 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013655 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013656 }
13657 elsif($New_Value eq "..." and $Old_Value ne "...")
13658 { # change from "int" to "..."
13659 if($ParamPos2==0)
13660 { # ISO C requires a named argument before "..."
13661 next;
13662 }
13663 $NewProblemType = "Parameter_Became_VaList";
13664 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013665 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013666 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013667 {
13668 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013669 if($Arch1 eq "unknown"
13670 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013671 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013672 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013673 ($Arch1, $Arch2) = ("unknown", "unknown");
13674 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013675 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013676 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013677 { # real
13678 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
13679 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
13680 }
13681 else
13682 { # model
13683 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13684 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13685 }
13686 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013687 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013688 if($Conv1{"Method"} eq "stack")
13689 {
13690 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
13691 $NewProblemType = "Parameter_Type_And_Stack";
13692 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013693 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013694 elsif($Conv1{"Method"} eq "reg")
13695 {
13696 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
13697 $NewProblemType = "Parameter_Type_And_Register";
13698 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013699 }
13700 }
13701 else
13702 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013703 if($Conv1{"Method"} eq "stack") {
13704 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013705 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013706 elsif($Conv1{"Method"} eq "register") {
13707 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013708 }
13709 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013710 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
13711 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013712 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013713 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013714 "Target"=>$PName1,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013715 "Param_Pos"=>$ParamPos1,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013716 "New_Signature"=>get_Signature($Symbol, 2) );
13717 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013718 }
13719 @RecurTypes = ();
13720 # checking type definition changes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013721 my %SubProblems_Merge = mergeTypes($PType1_Id, $PType2_Id, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013722 foreach my $SubProblemType (keys(%SubProblems_Merge))
13723 {
13724 foreach my $SubLocation (keys(%{$SubProblems_Merge{$SubProblemType}}))
13725 {
13726 my $NewProblemType = $SubProblemType;
13727 if($SubProblemType eq "DataType_Size")
13728 {
13729 my $InitialType_Type = $SubProblems_Merge{$SubProblemType}{$SubLocation}{"InitialType_Type"};
13730 if($InitialType_Type!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
13731 { # stack has been affected
13732 $NewProblemType = "DataType_Size_And_Stack";
13733 }
13734 }
13735 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013736 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013737 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013738 "Param_Pos"=>$ParamPos1,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013739 "Param_Name"=>$PName1 );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013740 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation}}{keys(%{$SubProblems_Merge{$SubProblemType}{$SubLocation}})} = values %{$SubProblems_Merge{$SubProblemType}{$SubLocation}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013741 if($SubLocation!~/\-\>/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013742 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation}{"Start_Type_Name"} = $TypeInfo{1}{$PType1_Id}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013743 }
13744 }
13745 }
13746}
13747
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013748sub find_ParamPair_Pos_byName($$$)
13749{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013750 my ($Name, $Symbol, $LibVersion) = @_;
13751 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013752 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013753 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
13754 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013755 {
13756 return $ParamPos;
13757 }
13758 }
13759 return "lost";
13760}
13761
13762sub find_ParamPair_Pos_byTypeAndPos($$$$$)
13763{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013764 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013765 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013766 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013767 {
13768 next if($Order eq "backward" and $ParamPos>$MediumPos);
13769 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013770 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
13771 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013772 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013773 push(@Positions, $ParamPos);
13774 }
13775 }
13776 return @Positions;
13777}
13778
13779sub getTypeIdByName($$)
13780{
13781 my ($TypeName, $Version) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013782 return $TName_Tid{$Version}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013783}
13784
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013785sub diffTypes($$$)
13786{
13787 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
13788 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
13789 }
13790 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
13791 { # skip recursive declarations
13792 return 0;
13793 }
13794
13795 pushType($_[0], $_[1], \@RecurTypes_Diff);
13796 my $Diff = diffTypes_I(@_);
13797 pop(@RecurTypes_Diff);
13798
13799 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
13800}
13801
13802sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013803{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013804 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013805
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013806 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
13807 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013808
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013809 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
13810 { # equal types
13811 return 0;
13812 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013813 if($Type1_Pure{"Name"} eq "void")
13814 { # from void* to something
13815 return 0;
13816 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013817 if($Type1_Pure{"Name"}=~/\*/
13818 or $Type2_Pure{"Name"}=~/\*/)
13819 { # compared in detectTypeChange()
13820 return 0;
13821 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013822
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013823 my %FloatType = map {$_=>1} (
13824 "float",
13825 "double",
13826 "long double"
13827 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013828
13829 my $T1 = $Type1_Pure{"Type"};
13830 my $T2 = $Type2_Pure{"Type"};
13831
13832 if($T1 eq "Struct"
13833 and $T2 eq "Class")
13834 { # compare as data structures
13835 $T2 = "Struct";
13836 }
13837
13838 if($T1 eq "Class"
13839 and $T2 eq "Struct")
13840 { # compare as data structures
13841 $T1 = "Struct";
13842 }
13843
13844 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013845 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013846 if($T1 eq "Intrinsic"
13847 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013848 { # "int" to "enum"
13849 return 0;
13850 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013851 elsif($T2 eq "Intrinsic"
13852 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013853 { # "enum" to "int"
13854 return 0;
13855 }
13856 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013857 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013858 # ...
13859 return 1;
13860 }
13861 }
13862 else
13863 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013864 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013865 {
13866 if($FloatType{$Type1_Pure{"Name"}}
13867 or $FloatType{$Type2_Pure{"Name"}})
13868 { # "float" to "double"
13869 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013870 if($Level eq "Source")
13871 { # Safe
13872 return 0;
13873 }
13874 else {
13875 return 1;
13876 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013877 }
13878 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013879 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013880 {
13881 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
13882 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013883 if(not @Membs1
13884 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040013885 { # private
13886 return 0;
13887 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013888 if($#Membs1!=$#Membs2)
13889 { # different number of elements
13890 return 1;
13891 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013892 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013893 {
13894 foreach my $Pos (@Membs1)
13895 { # compare elements by name and value
13896 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
13897 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
13898 { # different names
13899 return 1;
13900 }
13901 }
13902 }
13903 else
13904 {
13905 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013906 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013907 if($Level eq "Source")
13908 {
13909 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
13910 { # different names
13911 return 1;
13912 }
13913 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013914
13915 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
13916 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
13917
13918 if($MT1{"Name"} ne $MT2{"Name"}
13919 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
13920 {
13921 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
13922 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
13923
13924 if($PL1 ne $PL2)
13925 { # different pointer level
13926 return 1;
13927 }
13928
13929 # compare base types
13930 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
13931 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
13932
13933 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
13934 { # different types
13935 return 1;
13936 }
13937 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013938 }
13939 }
13940 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013941 else
13942 {
13943 # TODO: arrays, etc.
13944 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013945 }
13946 return 0;
13947}
13948
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013949sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013950{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013951 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013952 if(not $Type1_Id or not $Type2_Id) {
13953 return ();
13954 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013955 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013956 my %Type1 = get_Type($Type1_Id, 1);
13957 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013958 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
13959 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
13960 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
13961 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 +040013962
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013963 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
13964 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013965 return () if(not $Type1{"Name"} or not $Type2{"Name"});
13966 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
13967 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
13968 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
13969 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
13970 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
13971 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013972 if($Type1{"Name"} eq $Type2{"Name"})
13973 {
13974 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
13975 { # will be reported in mergeTypes() as typedef problem
13976 return ();
13977 }
13978 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
13979 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
13980 if(%Typedef_1 and %Typedef_2)
13981 {
13982 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
13983 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
13984 { # const Typedef
13985 return ();
13986 }
13987 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013988 }
13989 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
13990 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013991 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013992 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
13993 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013994 {
13995 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
13996 "Old_Value"=>$Type1_Base{"Name"},
13997 "New_Value"=>$Type2_Base{"Name"},
13998 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
13999 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE,
14000 "InitialType_Type"=>$Type1_Pure{"Type"});
14001 }
14002 else
14003 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014004 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014005 { # format change
14006 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14007 "Old_Value"=>$Type1_Base{"Name"},
14008 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014009 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
14010 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014011 "InitialType_Type"=>$Type1_Pure{"Type"});
14012 }
14013 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14014 {
14015 %{$LocalProblems{$Prefix."_BaseType"}}=(
14016 "Old_Value"=>$Type1_Base{"Name"},
14017 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014018 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
14019 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014020 "InitialType_Type"=>$Type1_Pure{"Type"});
14021 }
14022 }
14023 }
14024 }
14025 elsif($Type1{"Name"} ne $Type2{"Name"})
14026 { # type change
14027 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14028 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014029 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014030 and $Type1_Pure{"Name"} eq "void")
14031 {
14032 %{$LocalProblems{"Return_Type_From_Void"}}=(
14033 "New_Value"=>$Type2{"Name"},
14034 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE,
14035 "InitialType_Type"=>$Type1_Pure{"Type"});
14036 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014037 elsif($Prefix eq "Return"
14038 and $Type2_Pure{"Name"} eq "void")
14039 {
14040 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14041 "Old_Value"=>$Type1{"Name"},
14042 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
14043 "InitialType_Type"=>$Type1_Pure{"Type"});
14044 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014045 else
14046 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014047 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014048 and $Type1{"Size"} and $Type2{"Size"}
14049 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014050 {
14051 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14052 "Old_Value"=>$Type1{"Name"},
14053 "New_Value"=>$Type2{"Name"},
14054 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
14055 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE,
14056 "InitialType_Type"=>$Type1_Pure{"Type"});
14057 }
14058 else
14059 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014060 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014061 { # format change
14062 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14063 "Old_Value"=>$Type1{"Name"},
14064 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014065 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
14066 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014067 "InitialType_Type"=>$Type1_Pure{"Type"});
14068 }
14069 elsif(tNameLock($Type1_Id, $Type2_Id))
14070 { # FIXME: correct this condition
14071 %{$LocalProblems{$Prefix."_Type"}}=(
14072 "Old_Value"=>$Type1{"Name"},
14073 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014074 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
14075 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014076 "InitialType_Type"=>$Type1_Pure{"Type"});
14077 }
14078 }
14079 }
14080 }
14081 }
14082 if($Type1_PLevel!=$Type2_PLevel)
14083 {
14084 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14085 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14086 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014087 if($Level eq "Source")
14088 {
14089 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014090 "Old_Value"=>$Type1_PLevel,
14091 "New_Value"=>$Type2_PLevel);
14092 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014093 else
14094 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014095 if($Type2_PLevel>$Type1_PLevel)
14096 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014097 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
14098 "Old_Value"=>$Type1_PLevel,
14099 "New_Value"=>$Type2_PLevel);
14100 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014101 else
14102 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014103 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
14104 "Old_Value"=>$Type1_PLevel,
14105 "New_Value"=>$Type2_PLevel);
14106 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014107 }
14108 }
14109 }
14110 if($Type1_Pure{"Type"} eq "Array")
14111 { # base_type[N] -> base_type[N]
14112 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014113 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014114 foreach my $SubProblemType (keys(%SubProblems))
14115 {
14116 $SubProblemType=~s/_Type/_BaseType/g;
14117 next if(defined $LocalProblems{$SubProblemType});
14118 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
14119 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
14120 }
14121 }
14122 }
14123 return %LocalProblems;
14124}
14125
14126sub tNameLock($$)
14127{
14128 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014129 my $Changed = 0;
14130 if(differentDumps("G"))
14131 { # different GCC versions
14132 $Changed = 1;
14133 }
14134 elsif(differentDumps("V"))
14135 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014136 if(not checkDump(1, "2.20")
14137 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014138 { # latest names update
14139 # 2.6: added restrict qualifier
14140 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014141 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014142 $Changed = 1;
14143 }
14144 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014145
14146 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
14147 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
14148
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014149 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014150 { # different formats
14151 if($UseOldDumps)
14152 { # old dumps
14153 return 0;
14154 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014155
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014156 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
14157 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014158
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014159 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014160 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014161 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014162 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014163 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014164 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014165 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014166 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014167 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
14168 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
14169 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014170 { # equal base types
14171 return 0;
14172 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014173
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014174 if(not checkDump(1, "2.13")
14175 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014176 { # broken array names in ABI dumps < 2.13
14177 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014178 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014179 return 0;
14180 }
14181 }
14182
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014183 if(not checkDump(1, "2.6")
14184 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014185 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014186 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014187 and $TN2=~/\brestrict\b/) {
14188 return 0;
14189 }
14190 }
14191
14192 if(not checkDump(1, "2.20")
14193 or not checkDump(2, "2.20"))
14194 { # added restrict attribute in 2.6
14195 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
14196 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014197 return 0;
14198 }
14199 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014200 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014201 else
14202 {
14203 # typedef struct {...} type_t
14204 # typedef struct type_t {...} type_t
14205 if(index($TN1, " ".$TN2)!=-1)
14206 {
14207 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
14208 return 0;
14209 }
14210 }
14211 if(index($TN2, " ".$TN1)!=-1)
14212 {
14213 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
14214 return 0;
14215 }
14216 }
14217 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014218 return 1;
14219}
14220
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014221sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014222{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014223 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014224 if(defined $Cache{"differentDumps"}{$Check}) {
14225 return $Cache{"differentDumps"}{$Check};
14226 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014227 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014228 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014229 if($Check eq "G")
14230 {
14231 if(getGccVersion(1) ne getGccVersion(2))
14232 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014233 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014234 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014235 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014236 if($Check eq "V")
14237 {
14238 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
14239 formatVersion($UsedDump{2}{"V"}, 2))!=0)
14240 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014241 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014242 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014243 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014244 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014245 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014246}
14247
14248sub formatVersion($$)
14249{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014250 my ($V, $Digits) = @_;
14251 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014252 return join(".", splice(@Elems, 0, $Digits));
14253}
14254
14255sub htmlSpecChars($)
14256{
14257 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040014258 if(not $Str) {
14259 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014260 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014261 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
14262 $Str=~s/</&lt;/g;
14263 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
14264 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014265 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
14266 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014267 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014268 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014269 $Str=~s/\n/<br\/>/g;
14270 $Str=~s/\"/&quot;/g;
14271 $Str=~s/\'/&#39;/g;
14272 return $Str;
14273}
14274
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040014275sub xmlSpecChars($)
14276{
14277 my $Str = $_[0];
14278 if(not $Str) {
14279 return $Str;
14280 }
14281
14282 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
14283 $Str=~s/</&lt;/g;
14284 $Str=~s/>/&gt;/g;
14285
14286 $Str=~s/\"/&quot;/g;
14287 $Str=~s/\'/&#39;/g;
14288
14289 return $Str;
14290}
14291
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014292sub xmlSpecChars_R($)
14293{
14294 my $Str = $_[0];
14295 if(not $Str) {
14296 return $Str;
14297 }
14298
14299 $Str=~s/&amp;/&/g;
14300 $Str=~s/&lt;/</g;
14301 $Str=~s/&gt;/>/g;
14302
14303 $Str=~s/&quot;/"/g;
14304 $Str=~s/&#39;/'/g;
14305
14306 return $Str;
14307}
14308
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014309sub black_name($)
14310{
14311 my $Name = $_[0];
14312 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
14313}
14314
14315sub highLight_Signature($)
14316{
14317 my $Signature = $_[0];
14318 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
14319}
14320
14321sub highLight_Signature_Italic_Color($)
14322{
14323 my $Signature = $_[0];
14324 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
14325}
14326
14327sub separate_symbol($)
14328{
14329 my $Symbol = $_[0];
14330 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
14331 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
14332 ($Name, $Spec, $Ver) = ($1, $2, $3);
14333 }
14334 return ($Name, $Spec, $Ver);
14335}
14336
14337sub cut_f_attrs($)
14338{
14339 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
14340 return $2;
14341 }
14342 return "";
14343}
14344
14345sub highLight_Signature_PPos_Italic($$$$$)
14346{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014347 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
14348 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014349 if($CheckObjectsOnly) {
14350 $ItalicParams=$ColorParams=0;
14351 }
14352 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
14353 my $Return = "";
14354 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
14355 $Return = $2;
14356 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014357 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014358 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014359 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014360 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014361 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014362 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014363 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014364 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014365 }
14366 return $Signature;
14367 }
14368 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
14369 $Begin.=" " if($Begin!~/ \Z/);
14370 $End = cut_f_attrs($Signature);
14371 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040014372 my ($Short, $Params) = split_Signature($Signature);
14373 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014374 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014375 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014376 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014377 $Part=~s/\A\s+|\s+\Z//g;
14378 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
14379 if($Part=~/\([\*]+(\w+)\)/i) {
14380 $ParamName = $1;#func-ptr
14381 }
14382 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
14383 $ParamName = $1;
14384 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014385 if(not $ParamName)
14386 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014387 push(@Parts, $Part_Styled);
14388 next;
14389 }
14390 if($ItalicParams and not $TName_Tid{1}{$Part}
14391 and not $TName_Tid{2}{$Part})
14392 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014393 my $Style = "param";
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014394 if($Param_Pos ne ""
14395 and $Pos==$Param_Pos) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014396 $Style = "focus_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014397 }
14398 elsif($ColorParams) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014399 $Style = "color_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014400 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014401 $Part_Styled =~ s!(\W)$ParamName([\,\)]|\Z)!$1<span class=\'$Style\'>$ParamName</span>$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014402 }
14403 $Part_Styled=~s/,(\w)/, $1/g;
14404 push(@Parts, $Part_Styled);
14405 }
14406 if(@Parts)
14407 {
14408 foreach my $Num (0 .. $#Parts)
14409 {
14410 if($Num==$#Parts)
14411 { # add ")" to the last parameter
14412 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
14413 }
14414 elsif(length($Parts[$Num])<=45) {
14415 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
14416 }
14417 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014418 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014419 }
14420 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014421 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014422 }
14423 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014424 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014425 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014426 $Signature=~s!\[\]![&#160;]!g;
14427 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014428 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
14429 if($SymbolVersion) {
14430 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
14431 }
14432 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014433}
14434
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040014435sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014436{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040014437 my $Signature = $_[0];
14438 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
14439 {
14440 $Signature=~s/\A\Q$ShortName\E\(//g;
14441 cut_f_attrs($Signature);
14442 $Signature=~s/\)\Z//;
14443 return ($ShortName, $Signature);
14444 }
14445
14446 # error
14447 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014448}
14449
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040014450sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014451{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040014452 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014453 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014454 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
14455 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014456 foreach my $Pos (0 .. length($Params) - 1)
14457 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014458 my $S = substr($Params, $Pos, 1);
14459 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040014460 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014461 }
14462 if($S eq "," and
14463 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014464 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014465 if($Comma)
14466 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014467 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014468 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014469 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014470 }
14471 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014472 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014473 }
14474 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040014475 if(not $Sp)
14476 { # remove spaces
14477 foreach (@Parts)
14478 {
14479 s/\A //g;
14480 s/ \Z//g;
14481 }
14482 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014483 return @Parts;
14484}
14485
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014486sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014487{
14488 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014489 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014490 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014491 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
14492 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014493 $Center+=length($1);
14494 }
14495 foreach my $Pos (0 .. length($Sign)-1)
14496 {
14497 my $S = substr($Sign, $Pos, 1);
14498 if($S eq $Target)
14499 {
14500 if($B{"("}==$B{")"}
14501 and $B{"<"}==$B{">"}) {
14502 return $Center;
14503 }
14504 }
14505 if(defined $B{$S}) {
14506 $B{$S}+=1;
14507 }
14508 $Center+=1;
14509 }
14510 return 0;
14511}
14512
14513sub appendFile($$)
14514{
14515 my ($Path, $Content) = @_;
14516 return if(not $Path);
14517 if(my $Dir = get_dirname($Path)) {
14518 mkpath($Dir);
14519 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014520 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014521 print FILE $Content;
14522 close(FILE);
14523}
14524
14525sub writeFile($$)
14526{
14527 my ($Path, $Content) = @_;
14528 return if(not $Path);
14529 if(my $Dir = get_dirname($Path)) {
14530 mkpath($Dir);
14531 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014532 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014533 print FILE $Content;
14534 close(FILE);
14535}
14536
14537sub readFile($)
14538{
14539 my $Path = $_[0];
14540 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014541 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014542 local $/ = undef;
14543 my $Content = <FILE>;
14544 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014545 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014546 $Content=~s/\r/\n/g;
14547 }
14548 return $Content;
14549}
14550
14551sub get_filename($)
14552{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014553 if(defined $Cache{"get_filename"}{$_[0]}) {
14554 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014555 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014556 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
14557 return ($Cache{"get_filename"}{$_[0]}=$1);
14558 }
14559 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014560}
14561
14562sub get_dirname($)
14563{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014564 if(defined $Cache{"get_dirname"}{$_[0]}) {
14565 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014566 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014567 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
14568 return ($Cache{"get_dirname"}{$_[0]}=$1);
14569 }
14570 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014571}
14572
14573sub separate_path($) {
14574 return (get_dirname($_[0]), get_filename($_[0]));
14575}
14576
14577sub esc($)
14578{
14579 my $Str = $_[0];
14580 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
14581 return $Str;
14582}
14583
14584sub readLineNum($$)
14585{
14586 my ($Path, $Num) = @_;
14587 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014588 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014589 foreach (1 ... $Num) {
14590 <FILE>;
14591 }
14592 my $Line = <FILE>;
14593 close(FILE);
14594 return $Line;
14595}
14596
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014597sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014598{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014599 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014600 return () if(not $Path or not -f $Path);
14601 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014602 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
14603 {
14604 foreach my $AttrVal (split(/;/, $1))
14605 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014606 if($AttrVal=~/(.+):(.+)/)
14607 {
14608 my ($Name, $Value) = ($1, $2);
14609 $Attributes{$Name} = $Value;
14610 }
14611 }
14612 }
14613 return \%Attributes;
14614}
14615
14616sub is_abs($) {
14617 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
14618}
14619
14620sub get_abs_path($)
14621{ # abs_path() should NOT be called for absolute inputs
14622 # because it can change them
14623 my $Path = $_[0];
14624 if(not is_abs($Path)) {
14625 $Path = abs_path($Path);
14626 }
14627 return $Path;
14628}
14629
14630sub get_OSgroup()
14631{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014632 my $N = $Config{"osname"};
14633 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014634 return "macos";
14635 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014636 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014637 return "bsd";
14638 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014639 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014640 return "beos";
14641 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014642 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014643 return "symbian";
14644 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014645 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014646 return "windows";
14647 }
14648 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014649 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014650 }
14651}
14652
14653sub getGccVersion($)
14654{
14655 my $LibVersion = $_[0];
14656 if($GCC_VERSION{$LibVersion})
14657 { # dump version
14658 return $GCC_VERSION{$LibVersion};
14659 }
14660 elsif($UsedDump{$LibVersion}{"V"})
14661 { # old-version dumps
14662 return "unknown";
14663 }
14664 my $GccVersion = get_dumpversion($GCC_PATH); # host version
14665 if(not $GccVersion) {
14666 return "unknown";
14667 }
14668 return $GccVersion;
14669}
14670
14671sub showArch($)
14672{
14673 my $Arch = $_[0];
14674 if($Arch eq "arm"
14675 or $Arch eq "mips") {
14676 return uc($Arch);
14677 }
14678 return $Arch;
14679}
14680
14681sub getArch($)
14682{
14683 my $LibVersion = $_[0];
14684 if($CPU_ARCH{$LibVersion})
14685 { # dump version
14686 return $CPU_ARCH{$LibVersion};
14687 }
14688 elsif($UsedDump{$LibVersion}{"V"})
14689 { # old-version dumps
14690 return "unknown";
14691 }
14692 if(defined $Cache{"getArch"}{$LibVersion}) {
14693 return $Cache{"getArch"}{$LibVersion};
14694 }
14695 my $Arch = get_dumpmachine($GCC_PATH); # host version
14696 if(not $Arch) {
14697 return "unknown";
14698 }
14699 if($Arch=~/\A([\w]{3,})(-|\Z)/) {
14700 $Arch = $1;
14701 }
14702 $Arch = "x86" if($Arch=~/\Ai[3-7]86\Z/);
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040014703 if($OSgroup eq "windows")
14704 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014705 $Arch = "x86" if($Arch=~/win32|mingw32/i);
14706 $Arch = "x86_64" if($Arch=~/win64|mingw64/i);
14707 }
14708 $Cache{"getArch"}{$LibVersion} = $Arch;
14709 return $Arch;
14710}
14711
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014712sub get_Report_Header($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014713{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014714 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014715 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014716 if(getArch(1) ne getArch(2)
14717 or getArch(1) eq "unknown"
14718 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014719 { # don't show architecture in the header
14720 $ArchInfo="";
14721 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014722 my $Report_Header = "<h1><span class='nowrap'>";
14723 if($Level eq "Source") {
14724 $Report_Header .= "Source compatibility";
14725 }
14726 elsif($Level eq "Binary") {
14727 $Report_Header .= "Binary compatibility";
14728 }
14729 else {
14730 $Report_Header .= "API compatibility";
14731 }
14732 $Report_Header .= " report for the <span style='color:Blue;'>$TargetLibraryFName</span> $TargetComponent</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014733 $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>";
14734 if($AppPath) {
14735 $Report_Header .= " <span class='nowrap'>&#160;(relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)</span>";
14736 }
14737 $Report_Header .= "</h1>\n";
14738 return $Report_Header;
14739}
14740
14741sub get_SourceInfo()
14742{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014743 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014744 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014745 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014746 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014747 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014748 $CheckedHeaders = "<a name='Headers'></a><h2>Header Files (".($#Headers+1).")</h2><hr/>\n";
14749 $CheckedHeaders .= "<div class='h_list'>\n";
14750 foreach my $Header_Path (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
14751 {
14752 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
14753 my $Name = get_filename($Identity);
14754 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
14755 $CheckedHeaders .= $Name.$Comment."<br/>\n";
14756 }
14757 $CheckedHeaders .= "</div>\n";
14758 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014759 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014760
14761 if(my @Sources = keys(%{$Registered_Sources{1}}))
14762 {
14763 $CheckedSources = "<a name='Sources'></a><h2>Source Files (".($#Sources+1).")</h2><hr/>\n";
14764 $CheckedSources .= "<div class='h_list'>\n";
14765 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
14766 {
14767 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
14768 my $Name = get_filename($Identity);
14769 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
14770 $CheckedSources .= $Name.$Comment."<br/>\n";
14771 }
14772 $CheckedSources .= "</div>\n";
14773 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
14774 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014775 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014776 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014777 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014778 $CheckedLibs = "<a name='Libs'></a><h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2><hr/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014779 $CheckedLibs .= "<div class='lib_list'>\n";
14780 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
14781 {
14782 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
14783 $CheckedLibs .= $Library."<br/>\n";
14784 }
14785 $CheckedLibs .= "</div>\n";
14786 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014787 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014788 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
14789}
14790
14791sub get_ObjTitle()
14792{
14793 if(defined $UsedDump{1}{"DWARF"}) {
14794 return "Objects";
14795 }
14796 else {
14797 return ucfirst($SLIB_TYPE)." Libraries";
14798 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014799}
14800
14801sub get_TypeProblems_Count($$$)
14802{
14803 my ($TypeChanges, $TargetPriority, $Level) = @_;
14804 my $Type_Problems_Count = 0;
14805 foreach my $Type_Name (sort keys(%{$TypeChanges}))
14806 {
14807 my %Kinds_Target = ();
14808 foreach my $Kind (keys(%{$TypeChanges->{$Type_Name}}))
14809 {
14810 foreach my $Location (keys(%{$TypeChanges->{$Type_Name}{$Kind}}))
14811 {
14812 my $Target = $TypeChanges->{$Type_Name}{$Kind}{$Location}{"Target"};
14813 my $Priority = getProblemSeverity($Level, $Kind);
14814 next if($Priority ne $TargetPriority);
14815 if($Kinds_Target{$Kind}{$Target}) {
14816 next;
14817 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014818 if(cmpSeverities($Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target}, $Priority))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014819 { # select a problem with the highest priority
14820 next;
14821 }
14822 $Kinds_Target{$Kind}{$Target} = 1;
14823 $Type_Problems_Count += 1;
14824 }
14825 }
14826 }
14827 return $Type_Problems_Count;
14828}
14829
14830sub get_Summary($)
14831{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014832 my $Level = $_[0];
14833 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014834 $C_Problems_Low, $T_Problems_Medium, $T_Problems_Low, $I_Other, $T_Other, $C_Other) = (0,0,0,0,0,0,0,0,0,0,0,0);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014835 %{$RESULT{$Level}} = (
14836 "Problems"=>0,
14837 "Warnings"=>0,
14838 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014839 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014840 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014841 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014842 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014843 {
14844 if(not defined $CompatRules{$Level}{$Kind})
14845 { # unknown rule
14846 if(not $UnknownRules{$Level}{$Kind})
14847 { # only one warning
14848 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
14849 $UnknownRules{$Level}{$Kind}=1;
14850 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014851 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014852 }
14853 }
14854 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014855 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
14856 {
14857 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
14858 {
14859 if(not defined $CompatRules{$Level}{$Kind})
14860 { # unknown rule
14861 if(not $UnknownRules{$Level}{$Kind})
14862 { # only one warning
14863 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
14864 $UnknownRules{$Level}{$Kind}=1;
14865 }
14866 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
14867 }
14868 }
14869 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014870 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014871 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014872 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014873 {
14874 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
14875 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014876 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014877 {
14878 my $Priority = getProblemSeverity($Level, $Kind);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014879 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014880 $Added += 1;
14881 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014882 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014883 {
14884 $Removed += 1;
14885 $TotalAffected{$Level}{$Interface} = $Priority;
14886 }
14887 else
14888 {
14889 if($Priority eq "Safe") {
14890 $I_Other += 1;
14891 }
14892 elsif($Priority eq "High") {
14893 $I_Problems_High += 1;
14894 }
14895 elsif($Priority eq "Medium") {
14896 $I_Problems_Medium += 1;
14897 }
14898 elsif($Priority eq "Low") {
14899 $I_Problems_Low += 1;
14900 }
14901 if(($Priority ne "Low" or $StrictCompat)
14902 and $Priority ne "Safe") {
14903 $TotalAffected{$Level}{$Interface} = $Priority;
14904 }
14905 }
14906 }
14907 }
14908 }
14909 }
14910 my %TypeChanges = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014911 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014912 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014913 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014914 {
14915 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
14916 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014917 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014918 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014919 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
14920 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014921 my $Priority = getProblemSeverity($Level, $Kind);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014922 if(cmpSeverities($Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target}, $Priority))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014923 { # select a problem with the highest priority
14924 next;
14925 }
14926 if(($Priority ne "Low" or $StrictCompat)
14927 and $Priority ne "Safe") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014928 $TotalAffected{$Level}{$Interface} = maxSeverity($TotalAffected{$Level}{$Interface}, $Priority);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014929 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014930 %{$TypeChanges{$Type_Name}{$Kind}{$Location}} = %{$CompatProblems{$Level}{$Interface}{$Kind}{$Location}};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014931 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = maxSeverity($Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target}, $Priority);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014932 }
14933 }
14934 }
14935 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014936
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014937 $T_Problems_High = get_TypeProblems_Count(\%TypeChanges, "High", $Level);
14938 $T_Problems_Medium = get_TypeProblems_Count(\%TypeChanges, "Medium", $Level);
14939 $T_Problems_Low = get_TypeProblems_Count(\%TypeChanges, "Low", $Level);
14940 $T_Other = get_TypeProblems_Count(\%TypeChanges, "Safe", $Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014941
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014942 if($CheckObjectsOnly)
14943 { # only removed exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014944 $RESULT{$Level}{"Affected"} = $Removed*100/keys(%{$Symbol_Library{1}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014945 }
14946 else
14947 { # changed and removed public symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014948 my $SCount = keys(%{$CheckedSymbols{$Level}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014949 if($ExtendedCheck)
14950 { # don't count external_func_0 for constants
14951 $SCount-=1;
14952 }
14953 if($SCount)
14954 {
14955 my %Weight = (
14956 "High" => 100,
14957 "Medium" => 50,
14958 "Low" => 25
14959 );
14960 foreach (keys(%{$TotalAffected{$Level}})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014961 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014962 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014963 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014964 }
14965 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014966 $RESULT{$Level}{"Affected"} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014967 }
14968 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014969 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
14970 if($RESULT{$Level}{"Affected"}>=100) {
14971 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014972 }
14973
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014974 $RESULT{$Level}{"Problems"} += $Removed;
14975 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014976 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014977 if($StrictCompat) {
14978 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
14979 }
14980 else {
14981 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
14982 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014983
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014984 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014985 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014986 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014987 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014988 my $Severity = getProblemSeverity($Level, $Kind);
14989 if($Severity eq "Safe")
14990 {
14991 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014992 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014993 elsif($Severity eq "Low")
14994 {
14995 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014996 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014997 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014998 }
14999
15000 if($C_Problems_Low)
15001 {
15002 if($StrictCompat) {
15003 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
15004 }
15005 else {
15006 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015007 }
15008 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015009 if($CheckImpl and $Level eq "Binary")
15010 {
15011 if($StrictCompat) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015012 $RESULT{$Level}{"Problems"} += keys(%CompatProblems_Impl);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015013 }
15014 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015015 $RESULT{$Level}{"Warnings"} += keys(%CompatProblems_Impl);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015016 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015017 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015018 if($RESULT{$Level}{"Problems"}
15019 and $RESULT{$Level}{"Affected"}) {
15020 $RESULT{$Level}{"Verdict"} = "incompatible";
15021 }
15022 else {
15023 $RESULT{$Level}{"Verdict"} = "compatible";
15024 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015025
15026 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
15027 if(not $TotalTypes)
15028 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015029 $TotalTypes = keys(%{$TName_Tid{1}});
15030 }
15031
15032 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
15033 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
15034
15035 my ($TestInfo, $TestResults, $Problem_Summary) = ();
15036
15037 if($ReportFormat eq "xml")
15038 { # XML
15039 # test info
15040 $TestInfo .= " <library>$TargetLibraryName</library>\n";
15041 $TestInfo .= " <version1>\n";
15042 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
15043 $TestInfo .= " <architecture>$Arch1</architecture>\n";
15044 $TestInfo .= " <gcc>$GccV1</gcc>\n";
15045 $TestInfo .= " </version1>\n";
15046
15047 $TestInfo .= " <version2>\n";
15048 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
15049 $TestInfo .= " <architecture>$Arch2</architecture>\n";
15050 $TestInfo .= " <gcc>$GccV2</gcc>\n";
15051 $TestInfo .= " </version2>\n";
15052 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
15053
15054 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015055 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015056 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015057 $TestResults .= " <headers>\n";
15058 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15059 {
15060 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
15061 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15062 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15063 }
15064 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015065 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015066
15067 if(my @Sources = keys(%{$Registered_Sources{1}}))
15068 {
15069 $TestResults .= " <sources>\n";
15070 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15071 {
15072 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
15073 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15074 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15075 }
15076 $TestResults .= " </sources>\n";
15077 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015078
15079 $TestResults .= " <libs>\n";
15080 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15081 {
15082 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15083 $TestResults .= " <name>$Library</name>\n";
15084 }
15085 $TestResults .= " </libs>\n";
15086
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015087 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015088 $TestResults .= " <types>".$TotalTypes."</types>\n";
15089
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015090 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
15091 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015092 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
15093
15094 # problem summary
15095 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
15096 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
15097
15098 $Problem_Summary .= " <problems_with_types>\n";
15099 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
15100 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
15101 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
15102 $Problem_Summary .= " <safe>$T_Other</safe>\n";
15103 $Problem_Summary .= " </problems_with_types>\n";
15104
15105 $Problem_Summary .= " <problems_with_symbols>\n";
15106 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
15107 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
15108 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015109 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015110 $Problem_Summary .= " </problems_with_symbols>\n";
15111
15112 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015113 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015114 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015115 if($CheckImpl and $Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015116 {
15117 $Problem_Summary .= " <impl>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015118 $Problem_Summary .= " <low>".keys(%CompatProblems_Impl)."</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015119 $Problem_Summary .= " </impl>\n";
15120 }
15121 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
15122
15123 return ($TestInfo.$TestResults.$Problem_Summary, "");
15124 }
15125 else
15126 { # HTML
15127 # test info
15128 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015129 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015130 $TestInfo .= "<tr><th>".ucfirst($TargetComponent)." Name</th><td>$TargetLibraryFName</td></tr>\n";
15131
15132 my (@VInf1, @VInf2, $AddTestInfo) = ();
15133 if($Arch1 ne "unknown"
15134 and $Arch2 ne "unknown")
15135 { # CPU arch
15136 if($Arch1 eq $Arch2)
15137 { # go to the separate section
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015138 $AddTestInfo .= "<tr><th>CPU Type</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015139 }
15140 else
15141 { # go to the version number
15142 push(@VInf1, showArch($Arch1));
15143 push(@VInf2, showArch($Arch2));
15144 }
15145 }
15146 if($GccV1 ne "unknown"
15147 and $GccV2 ne "unknown"
15148 and $OStarget ne "windows")
15149 { # GCC version
15150 if($GccV1 eq $GccV2)
15151 { # go to the separate section
15152 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
15153 }
15154 else
15155 { # go to the version number
15156 push(@VInf1, "gcc ".$GccV1);
15157 push(@VInf2, "gcc ".$GccV2);
15158 }
15159 }
15160 # show long version names with GCC version and CPU architecture name (if different)
15161 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
15162 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
15163 $TestInfo .= $AddTestInfo;
15164 #if($COMMON_LANGUAGE{1}) {
15165 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
15166 #}
15167 if($ExtendedCheck) {
15168 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
15169 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015170 if($JoinReport)
15171 {
15172 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015173 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015174 }
15175 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015176 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015177 }
15178 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015179 $TestInfo .= "</table>\n";
15180
15181 # test results
15182 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015183 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015184
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015185 if(my @Headers = keys(%{$Registered_Headers{1}}))
15186 {
15187 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
15188 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
15189 }
15190 elsif($CheckObjectsOnly) {
15191 $TestResults .= "<tr><th>Total Header Files</th><td>0&#160;(not&#160;analyzed)</td></tr>\n";
15192 }
15193
15194 if(my @Sources = keys(%{$Registered_Sources{1}}))
15195 {
15196 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
15197 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
15198 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015199
15200 if(not $ExtendedCheck)
15201 {
15202 my $Libs_Link = "0";
15203 $Libs_Link = "<a href='#Libs' style='color:Blue;'>".keys(%{$Library_Symbol{1}})."</a>" if(keys(%{$Library_Symbol{1}})>0);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015204 $TestResults .= "<tr><th>Total ".get_ObjTitle()."</th><td>".($CheckHeadersOnly?"0&#160;(not&#160;analyzed)":$Libs_Link)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015205 }
15206
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015207 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015208
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015209 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015210 if($JoinReport) {
15211 $META_DATA = "kind:".lc($Level).";".$META_DATA;
15212 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015213 $TestResults .= "<tr><th>Verdict</th>";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015214 if($RESULT{$Level}{"Verdict"} eq "incompatible") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015215 $TestResults .= "<td><span style='color:Red;'><b>Incompatible<br/>(".$RESULT{$Level}{"Affected"}."%)</b></span></td>";
15216 }
15217 else {
15218 $TestResults .= "<td><span style='color:Green;'><b>Compatible</b></span></td>";
15219 }
15220 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015221 $TestResults .= "</table>\n";
15222
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015223 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015224 # problem summary
15225 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015226 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015227 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
15228
15229 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015230 if($Added>0)
15231 {
15232 if($JoinReport) {
15233 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
15234 }
15235 else {
15236 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
15237 }
15238 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015239 $META_DATA .= "added:$Added;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015240 $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 +040015241
15242 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015243 if($Removed>0)
15244 {
15245 if($JoinReport) {
15246 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
15247 }
15248 else {
15249 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
15250 }
15251 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015252 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015253 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
15254 $Problem_Summary .= "<td>High</td><td".getStyle("I", "R", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015255
15256 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015257 $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 +040015258 $TH_Link = "n/a" if($CheckObjectsOnly);
15259 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015260 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
15261 $Problem_Summary .= "<td>High</td><td".getStyle("T", "H", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015262
15263 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015264 $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 +040015265 $TM_Link = "n/a" if($CheckObjectsOnly);
15266 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015267 $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 +040015268
15269 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015270 $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 +040015271 $TL_Link = "n/a" if($CheckObjectsOnly);
15272 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015273 $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 +040015274
15275 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015276 $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 +040015277 $IH_Link = "n/a" if($CheckObjectsOnly);
15278 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015279 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
15280 $Problem_Summary .= "<td>High</td><td".getStyle("I", "H", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015281
15282 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015283 $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 +040015284 $IM_Link = "n/a" if($CheckObjectsOnly);
15285 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015286 $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 +040015287
15288 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015289 $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 +040015290 $IL_Link = "n/a" if($CheckObjectsOnly);
15291 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015292 $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 +040015293
15294 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015295 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
15296 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015297 }
15298 $ChangedConstants_Link = "n/a" if($CheckObjectsOnly);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015299 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015300 $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 +040015301
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015302 if($CheckImpl and $Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015303 {
15304 my $ChangedImpl_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015305 $ChangedImpl_Link = "<a href='#Changed_Implementation' style='color:Blue;'>".keys(%CompatProblems_Impl)."</a>" if(keys(%CompatProblems_Impl)>0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015306 $ChangedImpl_Link = "n/a" if($CheckHeadersOnly);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015307 $META_DATA .= "changed_implementation:".keys(%CompatProblems_Impl).";";
15308 $Problem_Summary .= "<tr><th>Problems with<br/>Implementation</th><td>Low</td><td".getStyle("Imp", "L", int(keys(%CompatProblems_Impl))).">$ChangedImpl_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015309 }
15310 # Safe Changes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015311 if($T_Other and not $CheckObjectsOnly)
15312 {
15313 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015314 $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 +040015315 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015316
15317 if($I_Other and not $CheckObjectsOnly)
15318 {
15319 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015320 $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 +040015321 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015322
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015323 if($C_Other and not $CheckObjectsOnly)
15324 {
15325 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
15326 $Problem_Summary .= "<tr><th>Other Changes<br/>in Constants</th><td>-</td><td".getStyle("C", "S", $C_Other).">$CS_Link</td></tr>\n";
15327 }
15328
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015329 $META_DATA .= "tool_version:$TOOL_VERSION";
15330 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015331 # $TestInfo = getLegend().$TestInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015332 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
15333 }
15334}
15335
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015336sub getStyle($$$)
15337{
15338 my ($Subj, $Act, $Num) = @_;
15339 my %Style = (
15340 "A"=>"new",
15341 "R"=>"failed",
15342 "S"=>"passed",
15343 "L"=>"warning",
15344 "M"=>"failed",
15345 "H"=>"failed"
15346 );
15347 if($Num>0) {
15348 return " class='".$Style{$Act}."'";
15349 }
15350 return "";
15351}
15352
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015353sub show_number($)
15354{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015355 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015356 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015357 my $Num = cut_off_number($_[0], 2, 0);
15358 if($Num eq "0")
15359 {
15360 foreach my $P (3 .. 7)
15361 {
15362 $Num = cut_off_number($_[0], $P, 1);
15363 if($Num ne "0") {
15364 last;
15365 }
15366 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015367 }
15368 if($Num eq "0") {
15369 $Num = $_[0];
15370 }
15371 return $Num;
15372 }
15373 return $_[0];
15374}
15375
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015376sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015377{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015378 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015379 if($num!~/\./)
15380 {
15381 $num .= ".";
15382 foreach (1 .. $digs_to_cut-1) {
15383 $num .= "0";
15384 }
15385 }
15386 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
15387 {
15388 foreach (1 .. $digs_to_cut - 1 - length($1)) {
15389 $num .= "0";
15390 }
15391 }
15392 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
15393 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
15394 }
15395 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015396 if($z) {
15397 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
15398 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015399 return $num;
15400}
15401
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015402sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015403{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015404 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015405 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015406
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015407 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015408 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
15409 {
15410 my $Header = $Constants{1}{$Constant}{"Header"};
15411 if(not $Header)
15412 { # added
15413 $Header = $Constants{2}{$Constant}{"Header"}
15414 }
15415
15416 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15417 {
15418 if(not defined $CompatRules{$Level}{$Kind}) {
15419 next;
15420 }
15421 if($TargetSeverity ne getProblemSeverity($Level, $Kind)) {
15422 next;
15423 }
15424 $ReportMap{$Header}{$Constant}{$Kind} = 1;
15425 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015426 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015427
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015428 if($ReportFormat eq "xml")
15429 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015430 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015431 {
15432 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015433 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015434 {
15435 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015436 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
15437 {
15438 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
15439 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
15440 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015441
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015442 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
15443 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
15444 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
15445 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
15446 $CHANGED_CONSTANTS .= " </problem>\n";
15447 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015448 $CHANGED_CONSTANTS .= " </constant>\n";
15449 }
15450 $CHANGED_CONSTANTS .= " </header>\n";
15451 }
15452 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
15453 }
15454 else
15455 { # HTML
15456 my $Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015457 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015458 {
15459 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015460 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015461 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015462 my $Report = "";
15463
15464 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
15465 {
15466 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
15467 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
15468 $Report .= "<tr><th>1</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
15469 $Number += 1;
15470 }
15471 if($Report)
15472 {
15473 $Report = $ContentDivStart."<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>".$Report."</table><br/>$ContentDivEnd\n";
15474 $Report = $ContentSpanStart."<span class='extendable'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
15475 $Report = insertIDs($Report);
15476 }
15477 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015478 }
15479 $CHANGED_CONSTANTS .= "<br/>\n";
15480 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015481 if($CHANGED_CONSTANTS)
15482 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015483 my $Title = "Problems with Constants, $TargetSeverity Severity";
15484 if($TargetSeverity eq "Safe")
15485 { # Safe Changes
15486 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015487 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015488 $CHANGED_CONSTANTS = "<a name='".get_Anchor("Constant", $Level, $TargetSeverity)."'></a><h2>$Title ($Number)</h2><hr/>\n".$CHANGED_CONSTANTS.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015489 }
15490 }
15491 return $CHANGED_CONSTANTS;
15492}
15493
15494sub get_Report_Impl()
15495{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015496 my $CHANGED_IMPLEMENTATION = "";
15497 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015498 foreach my $Interface (sort keys(%CompatProblems_Impl))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015499 {
15500 my $HeaderName = $CompleteSignature{1}{$Interface}{"Header"};
15501 my $DyLib = $Symbol_Library{1}{$Interface};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015502 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015503 }
15504 my $Changed_Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015505 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015506 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015507 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015508 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015509 my %NameSpaceSymbols = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015510 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015511 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015512 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015513 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015514 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015515 $CHANGED_IMPLEMENTATION .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015516 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015517 foreach my $Interface (@SortedInterfaces)
15518 {
15519 $Changed_Number += 1;
15520 my $Signature = get_Signature($Interface, 1);
15521 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015522 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015523 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015524 $CHANGED_IMPLEMENTATION .= $ContentSpanStart.highLight_Signature_Italic_Color($Signature).$ContentSpanEnd."<br/>\n".$ContentDivStart."<span class='mangled'>[symbol: <b>$Interface</b>]</span>".$CompatProblems_Impl{$Interface}{"Diff"}."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015525 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015526 $CHANGED_IMPLEMENTATION .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015527 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015528 }
15529 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015530 if($CHANGED_IMPLEMENTATION)
15531 {
15532 $CHANGED_IMPLEMENTATION = insertIDs($CHANGED_IMPLEMENTATION);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015533 $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 +040015534 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015535
15536 # clean memory
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015537 %CompatProblems_Impl = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015538
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015539 return $CHANGED_IMPLEMENTATION;
15540}
15541
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015542sub getTitle($$$)
15543{
15544 my ($Header, $Library, $NameSpace) = @_;
15545 my $Title = "";
15546 if($Library and $Library!~/\.\w+\Z/) {
15547 $Library .= " (.$LIB_EXT)";
15548 }
15549 if($Header and $Library)
15550 {
15551 $Title .= "<span class='h_name'>$Header</span>";
15552 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
15553 }
15554 elsif($Library) {
15555 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
15556 }
15557 elsif($Header) {
15558 $Title .= "<span class='h_name'>$Header</span><br/>\n";
15559 }
15560 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015561 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015562 }
15563 return $Title;
15564}
15565
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015566sub get_Report_Added($)
15567{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015568 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015569 my $ADDED_INTERFACES = "";
15570 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015571 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015572 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015573 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015574 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015575 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015576 {
15577 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
15578 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015579 if($Level eq "Source" and $ReportFormat eq "html")
15580 { # do not show library name in HTML report
15581 $DyLib = "";
15582 }
15583 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015584 }
15585 }
15586 }
15587 if($ReportFormat eq "xml")
15588 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015589 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015590 {
15591 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015592 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015593 {
15594 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015595 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015596 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
15597 }
15598 $ADDED_INTERFACES .= " </library>\n";
15599 }
15600 $ADDED_INTERFACES .= " </header>\n";
15601 }
15602 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
15603 }
15604 else
15605 { # HTML
15606 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015607 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015608 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015609 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015610 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015611 my %NameSpaceSymbols = ();
15612 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015613 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015614 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015615 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015616 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015617 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
15618 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015619 foreach my $Interface (@SortedInterfaces)
15620 {
15621 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015622 my $Signature = get_Signature($Interface, 2);
15623 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015624 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015625 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040015626 if($Interface=~/\A(_Z|\?)/)
15627 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015628 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015629 $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 +040015630 }
15631 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015632 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015633 }
15634 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040015635 else
15636 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015637 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015638 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015639 }
15640 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015641 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015642 }
15643 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015644 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015645 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015646 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015647 }
15648 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015649 if($ADDED_INTERFACES)
15650 {
15651 my $Anchor = "<a name='Added'></a>";
15652 if($JoinReport) {
15653 $Anchor = "<a name='".$Level."_Added'></a>";
15654 }
15655 $ADDED_INTERFACES = $Anchor."<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015656 }
15657 }
15658 return $ADDED_INTERFACES;
15659}
15660
15661sub get_Report_Removed($)
15662{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015663 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015664 my $REMOVED_INTERFACES = "";
15665 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015666 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015667 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015668 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015669 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015670 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015671 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015672 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
15673 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015674 if($Level eq "Source" and $ReportFormat eq "html")
15675 { # do not show library name in HTML report
15676 $DyLib = "";
15677 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015678 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015679 }
15680 }
15681 }
15682 if($ReportFormat eq "xml")
15683 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015684 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015685 {
15686 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015687 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015688 {
15689 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015690 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
15691 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015692 }
15693 $REMOVED_INTERFACES .= " </library>\n";
15694 }
15695 $REMOVED_INTERFACES .= " </header>\n";
15696 }
15697 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
15698 }
15699 else
15700 { # HTML
15701 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015702 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015703 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015704 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015705 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015706 my %NameSpaceSymbols = ();
15707 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015708 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015709 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015710 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015711 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015712 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
15713 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015714 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015715 {
15716 $Removed_Number += 1;
15717 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015718 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015719 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015720 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015721 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015722 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015723 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015724 if($Signature) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015725 $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 +040015726 }
15727 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015728 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015729 }
15730 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015731 else
15732 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015733 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015734 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015735 }
15736 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015737 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015738 }
15739 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015740 }
15741 }
15742 $REMOVED_INTERFACES .= "<br/>\n";
15743 }
15744 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015745 if($REMOVED_INTERFACES)
15746 {
15747 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
15748 if($JoinReport) {
15749 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
15750 }
15751 $REMOVED_INTERFACES = $Anchor."<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015752 }
15753 }
15754 return $REMOVED_INTERFACES;
15755}
15756
15757sub getXmlParams($$)
15758{
15759 my ($Content, $Problem) = @_;
15760 return "" if(not $Content or not $Problem);
15761 my %XMLparams = ();
15762 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
15763 {
15764 my $Macro = "\@".lc($Attr);
15765 if($Content=~/\Q$Macro\E/) {
15766 $XMLparams{lc($Attr)} = $Problem->{$Attr};
15767 }
15768 }
15769 my @PString = ();
15770 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015771 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015772 }
15773 if(@PString) {
15774 return " ".join(" ", @PString);
15775 }
15776 else {
15777 return "";
15778 }
15779}
15780
15781sub addMarkup($)
15782{
15783 my $Content = $_[0];
15784 # auto-markup
15785 $Content=~s/\n[ ]*//; # spaces
15786 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
15787 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015788 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015789 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
15790 if($Content=~/\ANOTE:/)
15791 { # notes
15792 $Content=~s!(NOTE):!<b>$1</b>:!g;
15793 }
15794 else {
15795 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
15796 }
15797 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
15798 my @Keywords = (
15799 "void",
15800 "const",
15801 "static",
15802 "restrict",
15803 "volatile",
15804 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015805 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015806 );
15807 my $MKeys = join("|", @Keywords);
15808 foreach (@Keywords) {
15809 $MKeys .= "|non-".$_;
15810 }
15811 $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 +040015812
15813 # Markdown
15814 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
15815 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015816 return $Content;
15817}
15818
15819sub applyMacroses($$$$)
15820{
15821 my ($Level, $Kind, $Content, $Problem) = @_;
15822 return "" if(not $Content or not $Problem);
15823 $Problem->{"Word_Size"} = $WORD_SIZE{2};
15824 $Content = addMarkup($Content);
15825 # macros
15826 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
15827 {
15828 my $Macro = "\@".lc($Attr);
15829 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015830 if(not defined $Value
15831 or $Value eq "") {
15832 next;
15833 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015834 if($Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015835 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015836 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
15837 $Value=~s/\s\w+(\)|,)/$1/g; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015838 $Value = black_name($Value);
15839 }
15840 elsif($Value=~/\s/) {
15841 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
15842 }
15843 elsif($Value=~/\A\d+\Z/
15844 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
15845 { # bits to bytes
15846 if($Value % $BYTE_SIZE)
15847 { # bits
15848 if($Value==1) {
15849 $Value = "<b>".$Value."</b> bit";
15850 }
15851 else {
15852 $Value = "<b>".$Value."</b> bits";
15853 }
15854 }
15855 else
15856 { # bytes
15857 $Value /= $BYTE_SIZE;
15858 if($Value==1) {
15859 $Value = "<b>".$Value."</b> byte";
15860 }
15861 else {
15862 $Value = "<b>".$Value."</b> bytes";
15863 }
15864 }
15865 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015866 else
15867 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015868 $Value = "<b>".htmlSpecChars($Value)."</b>";
15869 }
15870 $Content=~s/\Q$Macro\E/$Value/g;
15871 }
15872
15873 if($Content=~/(\A|[^\@\w])\@\w/)
15874 {
15875 if(not $IncompleteRules{$Level}{$Kind})
15876 { # only one warning
15877 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
15878 $IncompleteRules{$Level}{$Kind} = 1;
15879 }
15880 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015881 return $Content;
15882}
15883
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015884sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015885{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015886 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015887 my $INTERFACE_PROBLEMS = "";
15888 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015889 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015890 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015891 my ($SN, $SS, $SV) = separate_symbol($Symbol);
15892 if($SV and defined $CompatProblems{$Level}{$SN}) {
15893 next;
15894 }
15895 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015896 {
15897 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015898 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015899 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015900 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
15901 my $DyLib = $Symbol_Library{1}{$Symbol};
15902 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015903 { # Symbol with Version
15904 $DyLib = $Symbol_Library{1}{$VSym};
15905 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015906 if(not $DyLib)
15907 { # const global data
15908 $DyLib = "";
15909 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015910 if($Level eq "Source" and $ReportFormat eq "html")
15911 { # do not show library name in HTML report
15912 $DyLib = "";
15913 }
15914 %{$SymbolChanges{$Symbol}{$Kind}} = %{$CompatProblems{$Level}{$Symbol}{$Kind}};
15915 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015916 {
15917 my $Priority = getProblemSeverity($Level, $Kind);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015918 if($Priority ne $TargetSeverity) {
15919 delete($SymbolChanges{$Symbol}{$Kind}{$Location});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015920 }
15921 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015922 if(not keys(%{$SymbolChanges{$Symbol}{$Kind}}))
15923 {
15924 delete($SymbolChanges{$Symbol}{$Kind});
15925 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015926 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015927 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015928 }
15929 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015930 if(not keys(%{$SymbolChanges{$Symbol}})) {
15931 delete($SymbolChanges{$Symbol});
15932 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015933 }
15934 if($ReportFormat eq "xml")
15935 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015936 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015937 {
15938 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015939 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015940 {
15941 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015942 foreach my $Symbol (sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%SymbolChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015943 {
15944 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
15945 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
15946 {
15947 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
15948 {
15949 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015950 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015951 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
15952 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
15953 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
15954 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
15955 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
15956 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
15957 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
15958 $INTERFACE_PROBLEMS .= " </problem>\n";
15959 }
15960 }
15961 $INTERFACE_PROBLEMS .= " </symbol>\n";
15962 }
15963 $INTERFACE_PROBLEMS .= " </library>\n";
15964 }
15965 $INTERFACE_PROBLEMS .= " </header>\n";
15966 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015967 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015968 }
15969 else
15970 { # HTML
15971 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015972 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015973 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015974 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015975 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015976 my (%NameSpaceSymbols, %NewSignature) = ();
15977 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015978 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015979 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015980 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015981 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015982 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015983 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015984 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015985 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015986 my $Signature = get_Signature($Symbol, 1);
15987 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015988 my $ProblemNum = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015989 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015990 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015991 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015992 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015993 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015994 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015995 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015996 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015997 }
15998 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
15999 {
16000 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016001 $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 +040016002 $ProblemNum += 1;
16003 $ProblemsNum += 1;
16004 }
16005 }
16006 }
16007 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016008 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016009 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016010 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016011 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016012 $INTERFACE_PROBLEMS .= highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016013 }
16014 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016015 $INTERFACE_PROBLEMS .= $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016016 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016017 $INTERFACE_PROBLEMS .= " ($ProblemNum)".$ContentSpanEnd."<br/>\n";
16018 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
16019 if($NewSignature{$Symbol})
16020 { # argument list changed to
16021 $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 +040016022 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016023 if($Symbol=~/\A(_Z|\?)/) {
16024 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
16025 }
16026 $INTERFACE_PROBLEMS .= "<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>$SYMBOL_REPORT</table><br/>\n";
16027 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016028 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016029 $INTERFACE_PROBLEMS=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016030 }
16031 }
16032 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016033 $INTERFACE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016034 }
16035 }
16036 }
16037 if($INTERFACE_PROBLEMS)
16038 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016039 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
16040 my $Title = "Problems with Symbols, $TargetSeverity Severity";
16041 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016042 { # Safe Changes
16043 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016044 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016045 $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 +040016046 }
16047 }
16048 return $INTERFACE_PROBLEMS;
16049}
16050
16051sub get_Report_TypeProblems($$)
16052{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016053 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016054 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016055 my (%ReportMap, %TypeChanges) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016056 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016057 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016058 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016059 {
16060 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
16061 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016062 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016063 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016064 my $TypeName = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016065 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016066 my $Severity = getProblemSeverity($Level, $Kind);
16067 if($Severity eq "Safe"
16068 and $TargetSeverity ne "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016069 next;
16070 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016071
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016072 if(cmpSeverities($Type_MaxSeverity{$Level}{$TypeName}{$Kind}{$Target}, $Severity))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016073 { # select a problem with the highest priority
16074 next;
16075 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016076 %{$TypeChanges{$TypeName}{$Kind}{$Location}} = %{$CompatProblems{$Level}{$Interface}{$Kind}{$Location}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016077 }
16078 }
16079 }
16080 }
16081 my %Kinds_Locations = ();
16082 foreach my $TypeName (keys(%TypeChanges))
16083 {
16084 my %Kinds_Target = ();
16085 foreach my $Kind (sort keys(%{$TypeChanges{$TypeName}}))
16086 {
16087 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
16088 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016089 my $Severity = getProblemSeverity($Level, $Kind);
16090 if($Severity ne $TargetSeverity)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016091 { # other priority
16092 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16093 next;
16094 }
16095 $Kinds_Locations{$TypeName}{$Kind}{$Location} = 1;
16096 my $Target = $TypeChanges{$TypeName}{$Kind}{$Location}{"Target"};
16097 if($Kinds_Target{$Kind}{$Target})
16098 { # duplicate target
16099 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16100 next;
16101 }
16102 $Kinds_Target{$Kind}{$Target} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016103 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016104 $ReportMap{$HeaderName}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016105 }
16106 if(not keys(%{$TypeChanges{$TypeName}{$Kind}})) {
16107 delete($TypeChanges{$TypeName}{$Kind});
16108 }
16109 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016110 if(not keys(%{$TypeChanges{$TypeName}})) {
16111 delete($TypeChanges{$TypeName});
16112 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016113 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016114 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 +040016115 if($ReportFormat eq "xml")
16116 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016117 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016118 {
16119 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016120 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016121 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016122 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016123 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16124 {
16125 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
16126 {
16127 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16128 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16129 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16130 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16131 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16132 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
16133 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
16134 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16135 $TYPE_PROBLEMS .= " </problem>\n";
16136 }
16137 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016138 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016139 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016140 $TYPE_PROBLEMS .= showVTables($TypeName);
16141 }
16142 $TYPE_PROBLEMS .= " </type>\n";
16143 }
16144 $TYPE_PROBLEMS .= " </header>\n";
16145 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016146 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016147 }
16148 else
16149 { # HTML
16150 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016151 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016152 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016153 my (%NameSpace_Type) = ();
16154 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016155 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016156 }
16157 foreach my $NameSpace (sort keys(%NameSpace_Type))
16158 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016159 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016160 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 +040016161 foreach my $TypeName (@SortedTypes)
16162 {
16163 my $ProblemNum = 1;
16164 my $TYPE_REPORT = "";
16165 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16166 {
16167 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
16168 {
16169 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16170 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16171 {
16172 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
16173 $TYPE_REPORT .= "<tr><th>$ProblemNum</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
16174 $ProblemNum += 1;
16175 $ProblemsNum += 1;
16176 }
16177 }
16178 }
16179 $ProblemNum -= 1;
16180 if($TYPE_REPORT)
16181 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016182 my $Affected = getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016183 my $ShowVTables = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016184 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016185 $ShowVTables = showVTables($TypeName);
16186 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016187
16188 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ".show_Type($TypeName, 1, 1)." ($ProblemNum)".$ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016189 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
16190 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
16191 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
16192 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016193 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016194 $TYPE_PROBLEMS=~s/\b\Q$NameSpace\E::(\w|\~)/$1/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016195 }
16196 }
16197 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016198 $TYPE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016199 }
16200 }
16201 if($TYPE_PROBLEMS)
16202 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016203 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
16204 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016205 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016206 { # Safe Changes
16207 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016208 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016209 $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 +040016210 }
16211 }
16212 return $TYPE_PROBLEMS;
16213}
16214
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016215sub show_Type($$$)
16216{
16217 my ($Name, $Html, $LibVersion) = @_;
16218 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
16219 $TType = lc($TType);
16220 if($TType=~/struct|union|enum/) {
16221 $Name=~s/\A\Q$TType\E //g;
16222 }
16223 if($Html) {
16224 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
16225 }
16226 else {
16227 $Name = $TType." ".$Name;
16228 }
16229 return $Name;
16230}
16231
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016232sub get_Anchor($$$)
16233{
16234 my ($Kind, $Level, $Severity) = @_;
16235 if($JoinReport)
16236 {
16237 if($Severity eq "Safe") {
16238 return "Other_".$Level."_Changes_In_".$Kind."s";
16239 }
16240 else {
16241 return $Kind."_".$Level."_Problems_".$Severity;
16242 }
16243 }
16244 else
16245 {
16246 if($Severity eq "Safe") {
16247 return "Other_Changes_In_".$Kind."s";
16248 }
16249 else {
16250 return $Kind."_Problems_".$Severity;
16251 }
16252 }
16253}
16254
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016255sub showVTables($)
16256{
16257 my $TypeName = $_[0];
16258 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016259 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016260 if(defined $Type1{"VTable"}
16261 and keys(%{$Type1{"VTable"}}))
16262 {
16263 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016264 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016265 if(defined $Type2{"VTable"}
16266 and keys(%{$Type2{"VTable"}}))
16267 {
16268 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
16269 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016270 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016271 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016272 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
16273 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016274 }
16275 my $VTABLES = "";
16276 if($ReportFormat eq "xml")
16277 { # XML
16278 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016279 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016280 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016281 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016282 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
16283 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016284 $VTABLES .= " </entry>\n";
16285 }
16286 $VTABLES .= " </vtable>\n\n";
16287 }
16288 else
16289 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016290 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016291 $VTABLES .= "<tr><th width='2%'>Offset</th>";
16292 $VTABLES .= "<th width='45%'>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
16293 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016294 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016295 {
16296 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016297 if($Entries{$Index}{"E1"} ne $Entries{$Index}{"E2"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016298 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016299 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016300 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016301 $Color1 = " class='failed'";
16302 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016303 }
16304 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016305 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016306 }
16307 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016308 $VTABLES .= "<tr><th>".$Index."</th>\n";
16309 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
16310 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016311 }
16312 $VTABLES .= "</table><br/>\n";
16313 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016314 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016315 }
16316 return $VTABLES;
16317 }
16318 }
16319 return "";
16320}
16321
16322sub simpleVEntry($)
16323{
16324 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016325 if(not defined $VEntry
16326 or $VEntry eq "") {
16327 return "";
16328 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016329 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
16330 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
16331 if($VEntry=~/\A_ZThn.+\Z/) {
16332 $VEntry = "non-virtual thunk";
16333 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016334 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016335 # support for old GCC versions
16336 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
16337 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
16338 $VEntry=~s/\A&_Z\Z/& _Z/;
16339 # templates
16340 if($VEntry=~s/ \[with (\w+) = (.+?)(, [^=]+ = .+|])\Z//g)
16341 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
16342 # become std::basic_streambuf<char, ...>::imbue
16343 my ($Pname, $Pval) = ($1, $2);
16344 if($Pname eq "_CharT" and $VEntry=~/\Astd::/)
16345 { # stdc++ typedefs
16346 $VEntry=~s/<$Pname(, [^<>]+|)>/<$Pval>/g;
16347 # FIXME: simplify names using stdcxx typedefs (StdCxxTypedef)
16348 # The typedef info should be added to ABI dumps
16349 }
16350 else
16351 {
16352 $VEntry=~s/<$Pname>/<$Pval>/g;
16353 $VEntry=~s/<$Pname, [^<>]+>/<$Pval, ...>/g;
16354 }
16355 }
16356 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
16357 return $VEntry;
16358}
16359
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016360sub getAffectedSymbols($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016361{
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016362 my ($Level, $Target_TypeName, $Kinds_Locations, $Syms) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016363 my $LIMIT = 1000;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016364 if($#{$Syms}>=10000)
16365 { # reduce size of the report
16366 $LIMIT = 10;
16367 }
16368 my %SProblems = ();
16369 foreach my $Symbol (@{$Syms})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016370 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016371 if(keys(%SProblems)>$LIMIT) {
16372 last;
16373 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016374 if(($Symbol=~/C2E|D2E|D0E/))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016375 { # duplicated problems for C2 constructors, D2 and D0 destructors
16376 next;
16377 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016378 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16379 if($Level eq "Source")
16380 { # remove symbol version
16381 $Symbol=$SN;
16382 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016383 my ($MinPath_Length, $ProblemLocation_Last) = (-1, "");
16384 my $Severity_Max = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016385 my $Signature = get_Signature($Symbol, 1);
16386 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016387 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016388 foreach my $Location (keys(%{$CompatProblems{$Level}{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016389 {
16390 if(not defined $Kinds_Locations->{$Kind}
16391 or not $Kinds_Locations->{$Kind}{$Location}) {
16392 next;
16393 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016394 if($SV and defined $CompatProblems{$Level}{$SN}
16395 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Location})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016396 { # duplicated problems for versioned symbols
16397 next;
16398 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016399 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016400 next if($Type_Name ne $Target_TypeName);
16401
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016402 my $Position = $CompatProblems{$Level}{$Symbol}{$Kind}{$Location}{"Param_Pos"};
16403 my $Param_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Location}{"Param_Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016404 my $Severity = getProblemSeverity($Level, $Kind);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016405 my $Path_Length = 0;
16406 my $ProblemLocation = $Location;
16407 if($Type_Name) {
16408 $ProblemLocation=~s/->\Q$Type_Name\E\Z//g;
16409 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016410 while($ProblemLocation=~/\-\>/g) {
16411 $Path_Length += 1;
16412 }
16413 if($MinPath_Length==-1 or ($Path_Length<=$MinPath_Length and $Severity_Val{$Severity}>$Severity_Max)
16414 or (cmp_locations($ProblemLocation, $ProblemLocation_Last) and $Severity_Val{$Severity}==$Severity_Max))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016415 {
16416 $MinPath_Length = $Path_Length;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016417 $Severity_Max = $Severity_Val{$Severity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016418 $ProblemLocation_Last = $ProblemLocation;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016419 %{$SProblems{$Symbol}} = (
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016420 "Descr"=>getAffectDescription($Level, $Symbol, $Kind, $Location),
16421 "Severity_Max"=>$Severity_Max,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016422 "Signature"=>$Signature,
16423 "Position"=>$Position,
16424 "Param_Name"=>$Param_Name,
16425 "Location"=>$Location
16426 );
16427 }
16428 }
16429 }
16430 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016431 my @Symbols = keys(%SProblems);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016432 @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 +040016433 @Symbols = sort {$SProblems{$b}{"Severity_Max"}<=>$SProblems{$a}{"Severity_Max"}} @Symbols;
16434 if($#Symbols+1>$LIMIT)
16435 { # remove last element
16436 pop(@Symbols);
16437 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016438 my $Affected = "";
16439 if($ReportFormat eq "xml")
16440 { # XML
16441 $Affected .= " <affected>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016442 foreach my $Symbol (@Symbols)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016443 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016444 my $Param_Name = $SProblems{$Symbol}{"Param_Name"};
16445 my $Description = $SProblems{$Symbol}{"Descr"};
16446 my $Location = $SProblems{$Symbol}{"Location"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016447 my $Target = "";
16448 if($Param_Name) {
16449 $Target = " affected=\"param\" param_name=\"$Param_Name\"";
16450 }
16451 elsif($Location=~/\Aretval(\-|\Z)/i) {
16452 $Target = " affected=\"retval\"";
16453 }
16454 elsif($Location=~/\Athis(\-|\Z)/i) {
16455 $Target = " affected=\"this\"";
16456 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016457 $Affected .= " <symbol$Target name=\"$Symbol\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016458 $Affected .= " <comment>".xmlSpecChars($Description)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016459 $Affected .= " </symbol>\n";
16460 }
16461 $Affected .= " </affected>\n";
16462 }
16463 else
16464 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016465 foreach my $Symbol (@Symbols)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016466 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016467 my $Description = $SProblems{$Symbol}{"Descr"};
16468 my $Signature = $SProblems{$Symbol}{"Signature"};
16469 my $Pos = $SProblems{$Symbol}{"Position"};
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040016470 $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 +040016471 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016472 if(keys(%SProblems)>$LIMIT) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016473 $Affected .= "and others ...<br/>";
16474 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016475 $Affected = "<div class='affected'>".$Affected."</div>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016476 if($Affected)
16477 {
16478 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016479 $Affected = $ContentSpanStart_Affected."[+] affected symbols (".(keys(%SProblems)>$LIMIT?">".$LIMIT:keys(%SProblems)).")".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016480 }
16481 }
16482 return $Affected;
16483}
16484
16485sub cmp_locations($$)
16486{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016487 my ($L1, $L2) = @_;
16488 if($L2=~/\b(retval|this)\b/
16489 and $L1!~/\b(retval|this)\b/ and $L1!~/\-\>/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016490 return 1;
16491 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016492 if($L2=~/\b(retval|this)\b/ and $L2=~/\-\>/
16493 and $L1!~/\b(retval|this)\b/ and $L1=~/\-\>/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016494 return 1;
16495 }
16496 return 0;
16497}
16498
16499sub getAffectDescription($$$$)
16500{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016501 my ($Level, $Symbol, $Kind, $Location) = @_;
16502 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016503 my $PPos = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016504 my @Sentence = ();
16505 $Location=~s/\A(.*)\-\>.+?\Z/$1/;
16506 if($Kind eq "Overridden_Virtual_Method"
16507 or $Kind eq "Overridden_Virtual_Method_B") {
16508 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
16509 }
16510 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
16511 {
16512 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
16513 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016514 my $METHOD_TYPE = $CompleteSignature{1}{$Symbol}{"Constructor"}?"constructor":"method";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016515 my $ClassName = $TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016516 if($ClassName eq $Problem{"Type_Name"}) {
16517 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
16518 }
16519 else {
16520 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
16521 }
16522 }
16523 else
16524 {
16525 if($Location=~/retval/)
16526 { # return value
16527 if($Location=~/\-\>/) {
16528 push(@Sentence, "Field \'".$Location."\' in return value");
16529 }
16530 else {
16531 push(@Sentence, "Return value");
16532 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016533 if(my $Init = $Problem{"InitialType_Type"})
16534 {
16535 if($Init eq "Pointer") {
16536 push(@Sentence, "(pointer)");
16537 }
16538 elsif($Init eq "Ref") {
16539 push(@Sentence, "(reference)");
16540 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016541 }
16542 }
16543 elsif($Location=~/this/)
16544 { # "this" pointer
16545 if($Location=~/\-\>/) {
16546 push(@Sentence, "Field \'".$Location."\' in the object of this method");
16547 }
16548 else {
16549 push(@Sentence, "\'this\' pointer");
16550 }
16551 }
16552 else
16553 { # parameters
16554 if($Location=~/\-\>/) {
16555 push(@Sentence, "Field \'".$Location."\' in $PPos parameter");
16556 }
16557 else {
16558 push(@Sentence, "$PPos parameter");
16559 }
16560 if($Problem{"Param_Name"}) {
16561 push(@Sentence, "\'".$Problem{"Param_Name"}."\'");
16562 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016563 if(my $Init = $Problem{"InitialType_Type"})
16564 {
16565 if($Init eq "Pointer") {
16566 push(@Sentence, "(pointer)");
16567 }
16568 elsif($Init eq "Ref") {
16569 push(@Sentence, "(reference)");
16570 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016571 }
16572 }
16573 if($Location eq "this") {
16574 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
16575 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016576 elsif(defined $Problem{"Start_Type_Name"}
16577 and $Problem{"Start_Type_Name"} eq $Problem{"Type_Name"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016578 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
16579 }
16580 else {
16581 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
16582 }
16583 }
16584 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016585 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016586 push(@Sentence, " This is a symbol from an external library that may use the \'$TargetLibraryName\' library and change the ABI after recompiling.");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016587 }
16588 return join(" ", @Sentence);
16589}
16590
16591sub get_XmlSign($$)
16592{
16593 my ($Symbol, $LibVersion) = @_;
16594 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
16595 my $Report = "";
16596 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
16597 {
16598 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016599 my $Type = $Info->{"Param"}{$Pos}{"type"};
16600 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016601 foreach my $Typedef (keys(%ChangedTypedef))
16602 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016603 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
16604 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
16605 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016606 }
16607 $Report .= " <param pos=\"$Pos\">\n";
16608 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016609 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016610 $Report .= " </param>\n";
16611 }
16612 if(my $Return = $Info->{"Return"})
16613 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016614 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016615 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016616 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016617 $Report .= " </retval>\n";
16618 }
16619 return $Report;
16620}
16621
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016622sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016623{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016624 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016625 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016626 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016627 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016628 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16629 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016630 next;
16631 }
16632 $Report .= " <symbol name=\"$Symbol\">\n";
16633 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016634 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016635 {
16636 if(defined $CompleteSignature{1}{$Symbol}
16637 and defined $CompleteSignature{1}{$Symbol}{"Header"})
16638 {
16639 $P1 = get_XmlSign($Symbol, 1);
16640 $S1 = get_Signature($Symbol, 1);
16641 }
16642 elsif($Symbol=~/\A(_Z|\?)/) {
16643 $S1 = $tr_name{$Symbol};
16644 }
16645 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016646 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016647 {
16648 if(defined $CompleteSignature{2}{$Symbol}
16649 and defined $CompleteSignature{2}{$Symbol}{"Header"})
16650 {
16651 $P2 = get_XmlSign($Symbol, 2);
16652 $S2 = get_Signature($Symbol, 2);
16653 }
16654 elsif($Symbol=~/\A(_Z|\?)/) {
16655 $S2 = $tr_name{$Symbol};
16656 }
16657 }
16658 if($S1)
16659 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016660 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016661 $Report .= $P1;
16662 $Report .= " </old>\n";
16663 }
16664 if($S2 and $S2 ne $S1)
16665 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016666 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016667 $Report .= $P2;
16668 $Report .= " </new>\n";
16669 }
16670 $Report .= " </symbol>\n";
16671 }
16672 $Report .= "</symbols_info>\n";
16673 return $Report;
16674}
16675
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016676sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016677{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016678 my ($Level, $Report) = @_;
16679 if($ReportFormat eq "xml") {
16680 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016681 }
16682 if($StdOut)
16683 { # --stdout option
16684 print STDOUT $Report;
16685 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016686 else
16687 {
16688 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016689 mkpath(get_dirname($RPath));
16690
16691 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
16692 print REPORT $Report;
16693 close(REPORT);
16694
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016695 if($Browse or $OpenReport)
16696 { # open in browser
16697 openReport($RPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016698 if($JoinReport or $DoubleReport)
16699 {
16700 if($Level eq "Binary")
16701 { # wait to open a browser
16702 sleep(1);
16703 }
16704 }
16705 }
16706 }
16707}
16708
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016709sub openReport($)
16710{
16711 my $Path = $_[0];
16712 my $Cmd = "";
16713 if($Browse)
16714 { # user-defined browser
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040016715 $Cmd = $Browse." \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016716 }
16717 if(not $Cmd)
16718 { # default browser
16719 if($OSgroup eq "macos") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040016720 $Cmd = "open \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016721 }
16722 elsif($OSgroup eq "windows") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040016723 $Cmd = "start ".path_format($Path, $OSgroup);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016724 }
16725 else
16726 { # linux, freebsd, solaris
16727 my @Browsers = (
16728 "x-www-browser",
16729 "sensible-browser",
16730 "firefox",
16731 "opera",
16732 "xdg-open",
16733 "lynx",
16734 "links"
16735 );
16736 foreach my $Br (@Browsers)
16737 {
16738 if($Br = get_CmdPath($Br))
16739 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040016740 $Cmd = $Br." \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016741 last;
16742 }
16743 }
16744 }
16745 }
16746 if($Cmd)
16747 {
16748 if($Debug) {
16749 printMsg("INFO", "running $Cmd");
16750 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040016751 if($OSgroup ne "windows"
16752 and $OSgroup ne "macos")
16753 {
16754 if($Cmd!~/lynx|links/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016755 $Cmd .= " >\"/dev/null\" 2>&1 &";
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040016756 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016757 }
16758 system($Cmd);
16759 }
16760 else {
16761 printMsg("ERROR", "cannot open report in browser");
16762 }
16763}
16764
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016765sub getReport($)
16766{
16767 my $Level = $_[0];
16768 if($ReportFormat eq "xml")
16769 { # XML
16770
16771 if($Level eq "Join")
16772 {
16773 my $Report = "<reports>\n";
16774 $Report .= getReport("Binary");
16775 $Report .= getReport("Source");
16776 $Report .= "</reports>\n";
16777 return $Report;
16778 }
16779 else
16780 {
16781 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
16782 my ($Summary, $MetaData) = get_Summary($Level);
16783 $Report .= $Summary."\n";
16784 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
16785 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
16786 $Report .= get_Report_SymbolsInfo($Level);
16787 $Report .= "</report>\n";
16788 return $Report;
16789 }
16790 }
16791 else
16792 { # HTML
16793 my $CssStyles = readModule("Styles", "Report.css");
16794 my $JScripts = readModule("Scripts", "Sections.js");
16795 if($Level eq "Join")
16796 {
16797 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
16798 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040016799 my $Title = $TargetLibraryFName.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
16800 my $Keywords = $TargetLibraryFName.", compatibility, API, report";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016801 my $Description = "Compatibility report for the $TargetLibraryFName $TargetComponent between ".$Descriptor{1}{"Version"}." and ".$Descriptor{2}{"Version"}." versions";
16802 my ($BSummary, $BMetaData) = get_Summary("Binary");
16803 my ($SSummary, $SMetaData) = get_Summary("Source");
16804 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>";
16805 $Report .= get_Report_Header("Join")."
16806 <br/><div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016807 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
16808 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016809 </div>";
16810 $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>";
16811 $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 +040016812 $Report .= getReportFooter($TargetLibraryFName, not $JoinReport);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016813 $Report .= "\n<div style='height:999px;'></div>\n</body></html>";
16814 return $Report;
16815 }
16816 else
16817 {
16818 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040016819 my $Title = $TargetLibraryFName.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
16820 my $Keywords = $TargetLibraryFName.", ".lc($Level)." compatibility, API, report";
16821 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 +040016822 if($Level eq "Binary")
16823 {
16824 if(getArch(1) eq getArch(2)
16825 and getArch(1) ne "unknown") {
16826 $Description .= " on ".showArch(getArch(1));
16827 }
16828 }
16829 my $Report = "<!-\- $MetaData -\->\n".composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."\n<body>\n<div><a name='Top'></a>\n";
16830 $Report .= get_Report_Header($Level)."\n".$Summary."\n";
16831 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
16832 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
16833 $Report .= get_SourceInfo();
16834 $Report .= "</div>\n<br/><br/><br/><hr/>\n";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016835 $Report .= getReportFooter($TargetLibraryFName, not $JoinReport);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016836 $Report .= "\n<div style='height:999px;'></div>\n</body></html>";
16837 return $Report;
16838 }
16839 }
16840}
16841
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016842sub getLegend()
16843{
16844 return "<br/>
16845<table class='summary'>
16846<tr>
16847 <td class='new'>added</td>
16848 <td class='passed'>compatible</td>
16849</tr>
16850<tr>
16851 <td class='warning'>warning</td>
16852 <td class='failed'>incompatible</td>
16853</tr></table>\n";
16854}
16855
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016856sub createReport()
16857{
16858 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016859 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016860 writeReport("Join", getReport("Join"));
16861 }
16862 elsif($DoubleReport)
16863 { # default
16864 writeReport("Binary", getReport("Binary"));
16865 writeReport("Source", getReport("Source"));
16866 }
16867 elsif($BinaryOnly)
16868 { # --binary
16869 writeReport("Binary", getReport("Binary"));
16870 }
16871 elsif($SourceOnly)
16872 { # --source
16873 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016874 }
16875}
16876
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016877sub getReportFooter($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016878{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016879 my ($LibName, $Wide) = @_;
16880 my $FooterStyle = $Wide?"width:99%":"width:97%;padding-top:3px";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016881 my $Footer = "<div style='$FooterStyle;font-size:11px;' align='right'><i>Generated on ".(localtime time); # report date
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016882 $Footer .= " for <span style='font-weight:bold'>$LibName</span>"; # tested library/system name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016883 $Footer .= " by <a href='".$HomePage{"Wiki"}."'>ABI Compliance Checker</a>"; # tool name
16884 my $ToolSummary = "<br/>A tool for checking backward compatibility of a C/C++ library API&#160;&#160;";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016885 $Footer .= " $TOOL_VERSION &#160;$ToolSummary</i></div>"; # tool version
16886 return $Footer;
16887}
16888
16889sub get_Report_Problems($$)
16890{
16891 my ($Priority, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016892 my $Report = get_Report_TypeProblems($Priority, $Level);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016893 if(my $SProblems = get_Report_SymbolProblems($Priority, $Level)) {
16894 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016895 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016896 if($Priority eq "Low")
16897 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016898 $Report .= get_Report_ChangedConstants("Low", $Level);
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +040016899 if($ReportFormat eq "html")
16900 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016901 if($CheckImpl and $Level eq "Binary") {
16902 $Report .= get_Report_Impl();
16903 }
16904 }
16905 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016906 if($Priority eq "Safe")
16907 {
16908 $Report .= get_Report_ChangedConstants("Safe", $Level);
16909 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016910 if($ReportFormat eq "html")
16911 {
16912 if($Report)
16913 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016914 if($JoinReport)
16915 {
16916 if($Priority eq "Safe") {
16917 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
16918 }
16919 else {
16920 $Report = "<a name=\'".$Priority."_Risk_".$Level."_Problems\'></a>".$Report;
16921 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016922 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016923 else
16924 {
16925 if($Priority eq "Safe") {
16926 $Report = "<a name=\'Other_Changes\'></a>".$Report;
16927 }
16928 else {
16929 $Report = "<a name=\'".$Priority."_Risk_Problems\'></a>".$Report;
16930 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016931 }
16932 }
16933 }
16934 return $Report;
16935}
16936
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016937sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016938{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016939 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
16940 return "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
16941 <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
16942 <head>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016943 <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
16944 <meta name=\"keywords\" content=\"$Keywords\" />
16945 <meta name=\"description\" content=\"$Description\" />
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016946 <title>
16947 $Title
16948 </title>
16949 <style type=\"text/css\">
16950 $Styles
16951 </style>
16952 <script type=\"text/javascript\" language=\"JavaScript\">
16953 <!--
16954 $Scripts
16955 -->
16956 </script>
16957 </head>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016958}
16959
16960sub insertIDs($)
16961{
16962 my $Text = $_[0];
16963 while($Text=~/CONTENT_ID/)
16964 {
16965 if(int($Content_Counter)%2) {
16966 $ContentID -= 1;
16967 }
16968 $Text=~s/CONTENT_ID/c_$ContentID/;
16969 $ContentID += 1;
16970 $Content_Counter += 1;
16971 }
16972 return $Text;
16973}
16974
16975sub checkPreprocessedUnit($)
16976{
16977 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040016978 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016979 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016980 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016981
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040016982 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016983 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040016984 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016985 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040016986 chomp($Line);
16987 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016988 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040016989 $CurHeader = path_format($1, $OSgroup);
16990 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016991 $CurClass = "";
16992
16993 if(index($CurHeader, $TMP_DIR)==0) {
16994 next;
16995 }
16996
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016997 if(substr($CurHeaderName, 0, 1) eq "<")
16998 { # <built-in>, <command-line>, etc.
16999 $CurHeaderName = "";
17000 $CurHeader = "";
17001 }
17002
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017003 if($ExtraInfo)
17004 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017005 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017006 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
17007 }
17008 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017009 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017010 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017011 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017012 if($CurHeaderName)
17013 {
17014 if(not $Include_Neighbors{$Version}{$CurHeaderName}
17015 and not $Registered_Headers{$Version}{$CurHeader})
17016 { # not a target
17017 next;
17018 }
17019 if(not is_target_header($CurHeaderName, 1)
17020 and not is_target_header($CurHeaderName, 2))
17021 { # user-defined header
17022 next;
17023 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017024 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017025 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017026
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017027 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017028 {
17029 my ($Name, $Value) = ($1, $2);
17030 if(not $Constants{$Version}{$Name}{"Access"})
17031 {
17032 $Constants{$Version}{$Name}{"Access"} = "public";
17033 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017034 if($CurHeaderName) {
17035 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
17036 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017037 }
17038 }
17039 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
17040 $Constants{$Version}{$1}{"Access"} = "private";
17041 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017042 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017043 else
17044 {
17045 if(defined $ExtraDump)
17046 {
17047 if($Line=~/(\w+)\s*\(/)
17048 { # functions
17049 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17050 }
17051 #elsif($Line=~/(\w+)\s*;/)
17052 #{ # data
17053 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17054 #}
17055 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
17056 $CurClass = $2;
17057 }
17058 }
17059 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017060 }
17061 close(PREPROC);
17062 foreach my $Constant (keys(%{$Constants{$Version}}))
17063 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017064 if($Constants{$Version}{$Constant}{"Access"} eq "private")
17065 {
17066 delete($Constants{$Version}{$Constant});
17067 next;
17068 }
17069 if(not $ExtraDump and ($Constant=~/_h\Z/i or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
17070 { # skip
17071 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017072 }
17073 else {
17074 delete($Constants{$Version}{$Constant}{"Access"});
17075 }
17076 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017077 if($Debug)
17078 {
17079 mkpath($DEBUG_PATH{$Version});
17080 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
17081 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017082}
17083
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017084sub uncoverConstant($$)
17085{
17086 my ($LibVersion, $Constant) = @_;
17087 return "" if(not $LibVersion or not $Constant);
17088 return $Constant if(isCyclical(\@RecurConstant, $Constant));
17089 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
17090 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
17091 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017092
17093 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017094 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017095 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
17096 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017097 {
17098 push(@RecurConstant, $Constant);
17099 my $Uncovered = uncoverConstant($LibVersion, $Value);
17100 if($Uncovered ne "") {
17101 $Value = $Uncovered;
17102 }
17103 pop(@RecurConstant);
17104 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017105
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017106 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017107 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017108 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
17109 }
17110 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
17111}
17112
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017113sub simpleConstant($$)
17114{
17115 my ($LibVersion, $Value) = @_;
17116 if($Value=~/\W/)
17117 {
17118 my $Value_Copy = $Value;
17119 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
17120 {
17121 my $Word = $1;
17122 if($Value!~/$Word\s*\(/)
17123 {
17124 my $Val = uncoverConstant($LibVersion, $Word);
17125 if($Val ne "")
17126 {
17127 $Value=~s/\b$Word\b/$Val/g;
17128 }
17129 }
17130 }
17131 }
17132 return $Value;
17133}
17134
17135sub computeValue($)
17136{
17137 my $Value = $_[0];
17138
17139 if($Value=~/\A\((-?[\d]+)\)\Z/) {
17140 return $1;
17141 }
17142
17143 if($Value=~/\A[\d\-\+()]+\Z/) {
17144 return eval($Value);
17145 }
17146
17147 return $Value;
17148}
17149
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017150my %IgnoreConstant = map {$_=>1} (
17151 "VERSION",
17152 "VERSIONCODE",
17153 "VERNUM",
17154 "VERS_INFO",
17155 "PATCHLEVEL",
17156 "INSTALLPREFIX",
17157 "VBUILD",
17158 "VPATCH",
17159 "VMINOR",
17160 "BUILD_STRING",
17161 "BUILD_TIME",
17162 "PACKAGE_STRING",
17163 "PRODUCTION",
17164 "CONFIGURE_COMMAND",
17165 "INSTALLDIR",
17166 "BINDIR",
17167 "CONFIG_FILE_PATH",
17168 "DATADIR",
17169 "EXTENSION_DIR",
17170 "INCLUDE_PATH",
17171 "LIBDIR",
17172 "LOCALSTATEDIR",
17173 "SBINDIR",
17174 "SYSCONFDIR",
17175 "RELEASE",
17176 "SOURCE_ID",
17177 "SUBMINOR",
17178 "MINOR",
17179 "MINNOR",
17180 "MINORVERSION",
17181 "MAJOR",
17182 "MAJORVERSION",
17183 "MICRO",
17184 "MICROVERSION",
17185 "BINARY_AGE",
17186 "INTERFACE_AGE",
17187 "CORE_ABI",
17188 "PATCH",
17189 "COPYRIGHT",
17190 "TIMESTAMP",
17191 "REVISION",
17192 "PACKAGE_TAG",
17193 "PACKAGEDATE",
17194 "NUMVERSION",
17195 "Release",
17196 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017197);
17198
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017199sub constantFilter($$$)
17200{
17201 my ($Name, $Value, $Level) = @_;
17202
17203 if($Level eq "Binary")
17204 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017205 if($Name=~/_t\Z/)
17206 { # __malloc_ptr_t
17207 return 1;
17208 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017209 foreach (keys(%IgnoreConstant))
17210 {
17211 if($Name=~/(\A|_)$_(_|\Z)/)
17212 { # version
17213 return 1;
17214 }
17215 if(/\A[A-Z].*[a-z]\Z/)
17216 {
17217 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
17218 { # version
17219 return 1;
17220 }
17221 }
17222 }
17223 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
17224 { # version
17225 return 1;
17226 }
17227 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
17228 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
17229 return 1;
17230 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017231
17232 if($Value=~/\A["'].*['"]/i)
17233 { # string
17234 return 0;
17235 }
17236
17237 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
17238 { # static int gcry_pth_init
17239 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017240 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017241 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017242 return 1;
17243 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017244 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017245 { # foo(p)
17246 return 1;
17247 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017248 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017249 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017250 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017251 return 1;
17252 }
17253 }
17254
17255 return 0;
17256}
17257
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017258sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017259{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017260 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017261 foreach my $Constant (keys(%{$Constants{1}}))
17262 {
17263 if($SkipConstants{1}{$Constant})
17264 { # skipped by the user
17265 next;
17266 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017267
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017268 if(my $Header = $Constants{1}{$Constant}{"Header"})
17269 {
17270 if(not is_target_header($Header, 1)
17271 and not is_target_header($Header, 2))
17272 { # user-defined header
17273 next;
17274 }
17275 }
17276 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017277 next;
17278 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017279
17280 my $Old_Value = uncoverConstant(1, $Constant);
17281
17282 if(constantFilter($Constant, $Old_Value, $Level))
17283 { # separate binary and source problems
17284 next;
17285 }
17286
17287 if(not defined $Constants{2}{$Constant}{"Value"})
17288 { # removed
17289 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
17290 "Target"=>$Constant,
17291 "Old_Value"=>$Old_Value );
17292 next;
17293 }
17294
17295 if($Constants{2}{$Constant}{"Value"} eq "")
17296 { # empty value
17297 # TODO: implement a rule
17298 next;
17299 }
17300
17301 my $New_Value = uncoverConstant(2, $Constant);
17302
17303 my $Old_Value_Pure = $Old_Value;
17304 my $New_Value_Pure = $New_Value;
17305
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017306 $Old_Value_Pure=~s/(\W)\s+/$1/g;
17307 $Old_Value_Pure=~s/\s+(\W)/$1/g;
17308 $New_Value_Pure=~s/(\W)\s+/$1/g;
17309 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017310
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017311 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017312
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017313 if($New_Value_Pure ne $Old_Value_Pure)
17314 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017315 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
17316 { # complex values
17317 next;
17318 }
17319 if(computeValue($Old_Value) eq computeValue($New_Value))
17320 { # expressions
17321 next;
17322 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017323 if(convert_integer($Old_Value) eq convert_integer($New_Value))
17324 { # 0x0001 and 0x1, 0x1 and 1 equal constants
17325 next;
17326 }
17327 if($Old_Value eq "0" and $New_Value eq "NULL")
17328 { # 0 => NULL
17329 next;
17330 }
17331 if($Old_Value eq "NULL" and $New_Value eq "0")
17332 { # NULL => 0
17333 next;
17334 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017335 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017336 "Target"=>$Constant,
17337 "Old_Value"=>$Old_Value,
17338 "New_Value"=>$New_Value );
17339 }
17340 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017341
17342 foreach my $Constant (keys(%{$Constants{2}}))
17343 {
17344 if(not defined $Constants{1}{$Constant}{"Value"})
17345 {
17346 if($SkipConstants{2}{$Constant})
17347 { # skipped by the user
17348 next;
17349 }
17350
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017351 if(my $Header = $Constants{2}{$Constant}{"Header"})
17352 {
17353 if(not is_target_header($Header, 1)
17354 and not is_target_header($Header, 2))
17355 { # user-defined header
17356 next;
17357 }
17358 }
17359 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017360 next;
17361 }
17362
17363 my $New_Value = uncoverConstant(2, $Constant);
17364 if(not defined $New_Value or $New_Value eq "") {
17365 next;
17366 }
17367
17368 if(constantFilter($Constant, $New_Value, $Level))
17369 { # separate binary and source problems
17370 next;
17371 }
17372
17373 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
17374 "Target"=>$Constant,
17375 "New_Value"=>$New_Value );
17376 }
17377 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017378}
17379
17380sub convert_integer($)
17381{
17382 my $Value = $_[0];
17383 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017384 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017385 return hex($Value);
17386 }
17387 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017388 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017389 return oct($Value);
17390 }
17391 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017392 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017393 return oct($Value);
17394 }
17395 else {
17396 return $Value;
17397 }
17398}
17399
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017400sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017401{
17402 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017403 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017404 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017405 {
17406 if($LibVersion==1)
17407 {
17408 printMsg("WARNING", "checking headers only");
17409 $CheckHeadersOnly = 1;
17410 }
17411 else {
17412 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
17413 }
17414 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017415
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017416 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017417 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017418 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017419
17420 if($CheckUndefined)
17421 {
17422 my %UndefinedLibs = ();
17423
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017424 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
17425
17426 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017427 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017428 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017429 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017430 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017431 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017432 if($Symbol_Library{$LibVersion}{$Symbol}
17433 or $DepSymbol_Library{$LibVersion}{$Symbol})
17434 { # exported by target library
17435 next;
17436 }
17437 if(index($Symbol, '@')!=-1)
17438 { # exported default symbol version (@@)
17439 $Symbol=~s/\@/\@\@/;
17440 if($Symbol_Library{$LibVersion}{$Symbol}
17441 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
17442 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017443 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017444 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017445 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
17446 $UndefinedLibs{$Path} = 1;
17447 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017448 }
17449 }
17450 }
17451 if($ExtraInfo)
17452 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017453 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017454 {
17455 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017456 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017457 foreach (@Paths)
17458 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017459 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017460 my ($Dir, $Name) = separate_path($_);
17461
17462 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017463 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017464 }
17465
17466 $Name = parse_libname($Name, "name", $OStarget);
17467 $Name=~s/\Alib//;
17468
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017469 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017470 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017471
17472 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
17473 {
17474 $LibString = " -L".esc($Dir).$LibString;
17475 }
17476
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017477 writeFile($ExtraInfo."/libs-string", $LibString);
17478 }
17479 }
17480 }
17481
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017482 if($ExtraInfo) {
17483 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
17484 }
17485
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017486 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017487 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017488 if($#LibPaths!=-1)
17489 {
17490 if(not keys(%{$Symbol_Library{$LibVersion}}))
17491 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017492 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017493 printMsg("WARNING", "checking headers only");
17494 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017495 }
17496 }
17497 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017498
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017499 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017500 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017501}
17502
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017503my %Prefix_Lib_Map=(
17504 # symbols for autodetecting library dependencies (by prefix)
17505 "pthread_" => ["libpthread"],
17506 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
17507 "cairo_" => ["libcairo"],
17508 "gtk_" => ["libgtk-x11-2.0"],
17509 "atk_" => ["libatk-1.0"],
17510 "gdk_" => ["libgdk-x11-2.0"],
17511 "gl" => ["libGL"],
17512 "glu" => ["libGLU"],
17513 "popt" => ["libpopt"],
17514 "Py" => ["libpython"],
17515 "jpeg_" => ["libjpeg"],
17516 "BZ2_" => ["libbz2"],
17517 "Fc" => ["libfontconfig"],
17518 "Xft" => ["libXft"],
17519 "SSL_" => ["libssl"],
17520 "sem_" => ["libpthread"],
17521 "snd_" => ["libasound"],
17522 "art_" => ["libart_lgpl_2"],
17523 "dbus_g" => ["libdbus-glib-1"],
17524 "GOMP_" => ["libgomp"],
17525 "omp_" => ["libgomp"],
17526 "cms" => ["liblcms"]
17527);
17528
17529my %Pattern_Lib_Map=(
17530 "SL[a-z]" => ["libslang"]
17531);
17532
17533my %Symbol_Lib_Map=(
17534 # symbols for autodetecting library dependencies (by name)
17535 "pow" => "libm",
17536 "fmod" => "libm",
17537 "sin" => "libm",
17538 "floor" => "libm",
17539 "cos" => "libm",
17540 "dlopen" => "libdl",
17541 "deflate" => "libz",
17542 "inflate" => "libz",
17543 "move_panel" => "libpanel",
17544 "XOpenDisplay" => "libX11",
17545 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017546 "clock_gettime" => "librt",
17547 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017548);
17549
17550sub find_SymbolLibs($$)
17551{
17552 my ($LibVersion, $Symbol) = @_;
17553
17554 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
17555 { # debug symbols
17556 return ();
17557 }
17558
17559 my %Paths = ();
17560
17561 if(my $LibName = $Symbol_Lib_Map{$Symbol})
17562 {
17563 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
17564 $Paths{$Path} = 1;
17565 }
17566 }
17567
17568 if(my $SymbolPrefix = getPrefix($Symbol))
17569 {
17570 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
17571 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
17572 }
17573
17574 if(not keys(%Paths))
17575 {
17576 if(defined $Prefix_Lib_Map{$SymbolPrefix})
17577 {
17578 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
17579 {
17580 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
17581 $Paths{$Path} = 1;
17582 }
17583 }
17584 }
17585 }
17586
17587 if(not keys(%Paths))
17588 {
17589 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
17590 {
17591 if($Symbol=~/\A$Prefix/)
17592 {
17593 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
17594 {
17595 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
17596 $Paths{$Path} = 1;
17597 }
17598 }
17599 }
17600 }
17601 }
17602
17603 if(not keys(%Paths))
17604 {
17605 if($SymbolPrefix)
17606 { # try to find a library by symbol prefix
17607 if($SymbolPrefix eq "inotify" and
17608 index($Symbol, "\@GLIBC")!=-1)
17609 {
17610 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
17611 $Paths{$Path} = 1;
17612 }
17613 }
17614 else
17615 {
17616 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
17617 $Paths{$Path} = 1;
17618 }
17619 }
17620 }
17621 }
17622
17623 if(my @Paths = keys(%Paths)) {
17624 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
17625 }
17626 }
17627 return keys(%Paths);
17628}
17629
17630sub get_LibPath_Prefix($$)
17631{
17632 my ($LibVersion, $Prefix) = @_;
17633
17634 $Prefix = lc($Prefix);
17635 $Prefix=~s/[_]+\Z//g;
17636
17637 foreach ("-2", "2", "-1", "1", "")
17638 { # libgnome-2.so
17639 # libxml2.so
17640 # libdbus-1.so
17641 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
17642 return $Path;
17643 }
17644 }
17645 return "";
17646}
17647
17648sub getPrefix($)
17649{
17650 my $Str = $_[0];
17651 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
17652 { # XmuValidArea: Xmu
17653 return $1;
17654 }
17655 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
17656 { # snfReadFont: snf
17657 return $1;
17658 }
17659 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
17660 { # XRRTimes: XRR
17661 return $1;
17662 }
17663 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
17664 { # H5HF_delete: H5
17665 return $1;
17666 }
17667 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
17668 { # alarm_event_add: alarm_
17669 return $1;
17670 }
17671 elsif($Str=~/\A(([a-z])\2{1,})/i)
17672 { # ffopen
17673 return $1;
17674 }
17675 return "";
17676}
17677
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017678sub getSymbolSize($$)
17679{ # size from the shared library
17680 my ($Symbol, $LibVersion) = @_;
17681 return 0 if(not $Symbol);
17682 if(defined $Symbol_Library{$LibVersion}{$Symbol}
17683 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
17684 {
17685 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
17686 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
17687 {
17688 if($Size<0) {
17689 return -$Size;
17690 }
17691 }
17692 }
17693 return 0;
17694}
17695
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017696sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017697{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
17698 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017699 my ($Name, $Type) = @_;
17700
17701 # single
17702 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017703 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017704 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017705 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017706 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017707
17708 # double
17709 if($Name=~/$DEFAULT_STD_PARMS/)
17710 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040017711 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017712 {
17713 my ($ShortName, $FuncParams) = split_Signature($Name);
17714
17715 foreach my $FParam (separate_Params($FuncParams, 0, 0))
17716 {
17717 if(index($FParam, "<")!=-1)
17718 {
17719 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
17720 my $FParam_N = canonifyName($FParam, "T");
17721 if($FParam_N ne $FParam) {
17722 $Name=~s/\Q$FParam\E/$FParam_N/g;
17723 }
17724 }
17725 }
17726 }
17727 elsif($Type eq "T")
17728 {
17729 my ($ShortTmpl, $TmplParams) = template_Base($Name);
17730
17731 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040017732 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017733 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040017734 my $FParam = $TParams[0];
17735 foreach my $Pos (1 .. $#TParams)
17736 {
17737 my $TParam = $TParams[$Pos];
17738 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
17739 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
17740 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017741 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017742 }
17743 }
17744 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040017745 if($Type eq "S") {
17746 return formatName($Name, "S");
17747 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017748 return $Name;
17749}
17750
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017751sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017752{
17753 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017754 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017755 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017756 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017757 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017758 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017759 next if($tr_name{$Symbol});
17760 $Symbol=~s/[\@\$]+(.*)\Z//;
17761 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017762 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017763 elsif(index($Symbol, "?")==0)
17764 {
17765 next if($tr_name{$Symbol});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017766 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017767 }
17768 else
17769 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017770 $tr_name{$Symbol} = $Symbol;
17771 $mangled_name_gcc{$Symbol} = $Symbol;
17772 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017773 }
17774 }
17775 if($#MnglNames1 > -1)
17776 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017777 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017778 foreach my $MnglName (@MnglNames1)
17779 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017780 if(my $Unmangled = pop(@UnmangledNames))
17781 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040017782 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017783 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
17784 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
17785 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017786 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017787 and $tr_name{$MnglName}=~/vtable for (.+)/)
17788 { # bind class name and v-table symbol
17789 my $ClassName = $1;
17790 $ClassVTable{$ClassName} = $MnglName;
17791 $VTableClass{$MnglName} = $ClassName;
17792 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017793 }
17794 }
17795 }
17796 if($#MnglNames2 > -1)
17797 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017798 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017799 foreach my $MnglName (@MnglNames2)
17800 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017801 if(my $Unmangled = pop(@UnmangledNames))
17802 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017803 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017804 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
17805 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017806 }
17807 }
17808 return \%tr_name;
17809}
17810
17811sub link_symbol($$$)
17812{
17813 my ($Symbol, $RunWith, $Deps) = @_;
17814 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
17815 return 1;
17816 }
17817 if($Deps eq "+Deps")
17818 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017819 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017820 return 1;
17821 }
17822 }
17823 return 0;
17824}
17825
17826sub link_symbol_internal($$$)
17827{
17828 my ($Symbol, $RunWith, $Where) = @_;
17829 return 0 if(not $Where or not $Symbol);
17830 if($Where->{$RunWith}{$Symbol})
17831 { # the exact match by symbol name
17832 return 1;
17833 }
17834 if(my $VSym = $SymVer{$RunWith}{$Symbol})
17835 { # indirect symbol version, i.e.
17836 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017837 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017838 if($Where->{$RunWith}{$VSym}) {
17839 return 1;
17840 }
17841 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017842 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017843 if($Sym and $Ver)
17844 { # search for the symbol with the same version
17845 # or without version
17846 if($Where->{$RunWith}{$Sym})
17847 { # old: foo@v|foo@@v
17848 # new: foo
17849 return 1;
17850 }
17851 if($Where->{$RunWith}{$Sym."\@".$Ver})
17852 { # old: foo|foo@@v
17853 # new: foo@v
17854 return 1;
17855 }
17856 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
17857 { # old: foo|foo@v
17858 # new: foo@@v
17859 return 1;
17860 }
17861 }
17862 return 0;
17863}
17864
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017865sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017866{
17867 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017868 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017869 my @Imported = ();
17870 if($OSgroup eq "macos")
17871 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017872 my $NM = get_CmdPath("nm");
17873 if(not $NM) {
17874 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017875 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017876 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017877 while(<APP>)
17878 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017879 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017880 push(@Imported, $1);
17881 }
17882 }
17883 close(APP);
17884 }
17885 elsif($OSgroup eq "windows")
17886 {
17887 my $DumpBinCmd = get_CmdPath("dumpbin");
17888 if(not $DumpBinCmd) {
17889 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
17890 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017891 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017892 while(<APP>)
17893 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017894 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
17895 push(@Imported, $1);
17896 }
17897 }
17898 close(APP);
17899 }
17900 else
17901 {
17902 my $ReadelfCmd = get_CmdPath("readelf");
17903 if(not $ReadelfCmd) {
17904 exitStatus("Not_Found", "can't find \"readelf\"");
17905 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017906 open(APP, "$ReadelfCmd -WhlSsdA \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017907 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017908 while(<APP>)
17909 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017910 if(defined $symtab)
17911 { # do nothing with symtab
17912 if(index($_, "'.dynsym'")!=-1)
17913 { # dynamic table
17914 $symtab = undef;
17915 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017916 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017917 elsif(index($_, "'.symtab'")!=-1)
17918 { # symbol table
17919 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017920 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017921 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017922 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017923 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
17924 if($Ndx eq "UND")
17925 { # only imported symbols
17926 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017927 }
17928 }
17929 }
17930 close(APP);
17931 }
17932 return @Imported;
17933}
17934
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017935my %ELF_BIND = map {$_=>1} (
17936 "WEAK",
17937 "GLOBAL"
17938);
17939
17940my %ELF_TYPE = map {$_=>1} (
17941 "FUNC",
17942 "IFUNC",
17943 "OBJECT",
17944 "COMMON"
17945);
17946
17947my %ELF_VIS = map {$_=>1} (
17948 "DEFAULT",
17949 "PROTECTED"
17950);
17951
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017952sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017953{ # read the line of 'readelf' output corresponding to the symbol
17954 my @Info = split(/\s+/, $_[0]);
17955 # Num: Value Size Type Bind Vis Ndx Name
17956 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017957 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017958 shift(@Info); # spaces
17959 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017960
17961 if($#Info==7)
17962 { # UND SYMBOL (N)
17963 if($Info[7]=~/\(\d+\)/) {
17964 pop(@Info);
17965 }
17966 }
17967
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017968 if($#Info!=6)
17969 { # other lines
17970 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017971 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017972 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017973 return () if(not defined $ELF_BIND{$Info[3]});
17974 return () if(not defined $ELF_VIS{$Info[4]});
17975 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
17976 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
17977 return ();
17978 }
17979 if($OStarget eq "symbian")
17980 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
17981 if(index($Info[6], "_._.absent_export_")!=-1)
17982 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
17983 return ();
17984 }
17985 $Info[6]=~s/\@.+//g; # remove version
17986 }
17987 if(index($Info[2], "0x") == 0)
17988 { # size == 0x3d158
17989 $Info[2] = hex($Info[2]);
17990 }
17991 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017992}
17993
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017994sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017995{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017996 my ($LibVersion, $Name) = @_;
17997 return "" if(not $LibVersion or not $Name);
17998 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
17999 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018000 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018001 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
18002}
18003
18004sub get_LibPath_I($$)
18005{
18006 my ($LibVersion, $Name) = @_;
18007 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018008 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018009 if(-f $Name)
18010 { # absolute path
18011 return $Name;
18012 }
18013 else
18014 { # broken
18015 return "";
18016 }
18017 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018018 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018019 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018020 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018021 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018022 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018023 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018024 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018025 }
18026 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
18027 { # ldconfig default paths
18028 return $DefaultPath;
18029 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018030 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018031 { # search in default linker directories
18032 # and then in all system paths
18033 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018034 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018035 }
18036 }
18037 detectSystemObjects() if(not keys(%SystemObjects));
18038 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
18039 return $AllObjects[0];
18040 }
18041 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
18042 {
18043 if($ShortName ne $Name)
18044 { # FIXME: check this case
18045 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
18046 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018047 }
18048 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018049 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018050 # can't find
18051 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018052}
18053
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018054sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018055{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018056 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
18057 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018058
18059 my $Real_Path = realpath($Lib_Path);
18060
18061 if(not $Real_Path)
18062 { # broken link
18063 return ();
18064 }
18065
18066 my $Lib_Name = get_filename($Real_Path);
18067
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018068 if($ExtraInfo)
18069 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018070 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018071 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018072 }
18073
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018074 if($IsNeededLib)
18075 {
18076 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
18077 return ();
18078 }
18079 }
18080 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018081 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018082
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018083 if($CheckImpl)
18084 {
18085 if(not $IsNeededLib) {
18086 getImplementations($LibVersion, $Lib_Path);
18087 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018088 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018089
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018090 push(@RecurLib, $Lib_Name);
18091 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018092 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
18093
18094 if(not $IsNeededLib)
18095 { # special cases: libstdc++ and libc
18096 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
18097 {
18098 if($ShortName eq "libstdc++")
18099 { # libstdc++.so.6
18100 $STDCXX_TESTING = 1;
18101 }
18102 elsif($ShortName eq "libc")
18103 { # libc-2.11.3.so
18104 $GLIBC_TESTING = 1;
18105 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018106 }
18107 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018108 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018109 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018110 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018111 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018112 mkpath(get_dirname($DebugPath));
18113 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018114 if($OStarget eq "macos")
18115 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018116 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018117 if(not $NM) {
18118 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018119 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018120 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018121 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018122 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018123 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018124 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018125 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018126 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018127 else
18128 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018129 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018130 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018131 while(<LIB>)
18132 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018133 if($CheckUndefined)
18134 {
18135 if(not $IsNeededLib)
18136 {
18137 if(/ U _([\w\$]+)\s*\Z/)
18138 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018139 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018140 next;
18141 }
18142 }
18143 }
18144
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018145 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018146 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018147 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018148 if($IsNeededLib)
18149 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018150 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018151 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018152 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18153 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018154 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018155 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018156 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018157 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018158 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18159 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018160 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18161 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018162 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018163 setLanguage($LibVersion, "C++");
18164 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018165 }
18166 if($CheckObjectsOnly
18167 and $LibVersion==1) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018168 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018169 }
18170 }
18171 }
18172 }
18173 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018174
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018175 if($Deps)
18176 {
18177 if($LIB_TYPE eq "dynamic")
18178 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018179
18180 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018181 if(not $OtoolCmd) {
18182 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018183 }
18184
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018185 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
18186 while(<LIB>)
18187 {
18188 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
18189 and $1 ne $Lib_Path) {
18190 $NeededLib{$1} = 1;
18191 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018192 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018193 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018194 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018195 }
18196 }
18197 elsif($OStarget eq "windows")
18198 { # Windows *.dll, *.lib
18199 my $DumpBinCmd = get_CmdPath("dumpbin");
18200 if(not $DumpBinCmd) {
18201 exitStatus("Not_Found", "can't find \"dumpbin\"");
18202 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018203 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018204 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018205 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018206 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018207 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018208 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018209 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018210 else
18211 { # write to pipe
18212 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018213 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018214 while(<LIB>)
18215 { # 1197 4AC 0000A620 SetThreadStackGuarantee
18216 # 1198 4AD SetThreadToken (forwarded to ...)
18217 # 3368 _o2i_ECPublicKey
18218 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*\Z/i
18219 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
18220 or /\A\s*\d+\s+_([\w\?\@]+)\s*\Z/)
18221 { # dynamic, static and forwarded symbols
18222 my $realname = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018223 if($IsNeededLib)
18224 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018225 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018226 {
18227 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
18228 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
18229 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018230 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018231 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018232 {
18233 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
18234 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018235 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18236 {
18237 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
18238 setLanguage($LibVersion, "C++");
18239 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018240 }
18241 if($CheckObjectsOnly
18242 and $LibVersion==1) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018243 $CheckedSymbols{"Binary"}{$realname} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018244 }
18245 }
18246 }
18247 }
18248 close(LIB);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018249 if($Deps)
18250 {
18251 if($LIB_TYPE eq "dynamic")
18252 { # dependencies
18253 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
18254 while(<LIB>)
18255 {
18256 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
18257 and $1 ne $Lib_Path) {
18258 $NeededLib{path_format($1, $OSgroup)} = 1;
18259 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018260 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018261 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018262 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018263 }
18264 }
18265 else
18266 { # Unix; *.so, *.a
18267 # Symbian: *.dso, *.lib
18268 my $ReadelfCmd = get_CmdPath("readelf");
18269 if(not $ReadelfCmd) {
18270 exitStatus("Not_Found", "can't find \"readelf\"");
18271 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018272 $ReadelfCmd .= " -WhlSsdA \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
18273 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018274 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018275 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018276 system($ReadelfCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018277 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018278 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018279 else
18280 { # write to pipe
18281 open(LIB, $ReadelfCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018282 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018283 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018284 while(<LIB>)
18285 {
18286 if($LIB_TYPE eq "dynamic")
18287 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018288 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018289 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018290 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018291 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018292 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018293 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018294 # do nothing with symtab
18295 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018296 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018297 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018298 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018299 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018300 next;
18301 }
18302 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018303 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018304 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018305 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018306 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018307 if($CheckUndefined)
18308 {
18309 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018310 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018311 }
18312 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018313 next;
18314 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040018315 if($Bind eq "WEAK")
18316 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018317 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040018318 if($Weak eq "-Weak")
18319 { # skip WEAK symbols
18320 next;
18321 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018322 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018323 my $Short = $Symbol;
18324 $Short=~s/\@.+//g;
18325 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018326 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018327 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
18328 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018329 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018330 if($IsNeededLib)
18331 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018332 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018333 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018334 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18335 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018336 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018337 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018338 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018339 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018340 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18341 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
18342 if($Vers)
18343 {
18344 if($LIB_EXT eq "so")
18345 { # value
18346 $Interface_Value{$LibVersion}{$Symbol} = $Value;
18347 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
18348 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018349 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018350 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18351 {
18352 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
18353 setLanguage($LibVersion, "C++");
18354 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018355 }
18356 if($CheckObjectsOnly
18357 and $LibVersion==1) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018358 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018359 }
18360 }
18361 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018362 elsif($LIB_TYPE eq "dynamic")
18363 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018364 if($Deps)
18365 {
18366 if(/NEEDED.+\[([^\[\]]+)\]/)
18367 { # dependencies:
18368 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
18369 $NeededLib{$1} = 1;
18370 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018371 }
18372 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018373 }
18374 close(LIB);
18375 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018376 if($Vers)
18377 {
18378 if(not $IsNeededLib and $LIB_EXT eq "so")
18379 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018380 my %Found = ();
18381
18382 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018383 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018384 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018385 next if(index($Symbol,"\@")==-1);
18386 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018387 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018388 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018389 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018390 if($Symbol_SameValue ne $Symbol
18391 and index($Symbol_SameValue,"\@")==-1)
18392 {
18393 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018394 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018395 last;
18396 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018397 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018398 }
18399 }
18400
18401 # default
18402 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
18403 {
18404 next if(defined $Found{$Symbol});
18405 next if(index($Symbol,"\@\@")==-1);
18406
18407 if($Symbol=~/\A([^\@]*)\@\@/
18408 and not $SymVer{$LibVersion}{$1})
18409 {
18410 $SymVer{$LibVersion}{$1} = $Symbol;
18411 $Found{$Symbol} = 1;
18412 }
18413 }
18414
18415 # non-default
18416 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
18417 {
18418 next if(defined $Found{$Symbol});
18419 next if(index($Symbol,"\@")==-1);
18420
18421 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
18422 and not $SymVer{$LibVersion}{$1})
18423 {
18424 $SymVer{$LibVersion}{$1} = $Symbol;
18425 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018426 }
18427 }
18428 }
18429 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018430 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018431 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018432 foreach my $DyLib (sort keys(%NeededLib))
18433 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018434 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
18435
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018436 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
18437 {
18438 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
18439 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
18440 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018441 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018442 }
18443 }
18444 pop(@RecurLib);
18445 return $Library_Symbol{$LibVersion};
18446}
18447
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018448sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018449{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018450 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018451 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018452 return keys(%Prefixes);
18453}
18454
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018455sub get_prefixes_I($$)
18456{
18457 foreach my $P (@{$_[0]})
18458 {
18459 my @Parts = reverse(split(/[\/\\]+/, $P));
18460 my $Name = $Parts[0];
18461 foreach (1 .. $#Parts)
18462 {
18463 $_[1]->{$Name}{$P} = 1;
18464 last if($_>4 or $Parts[$_] eq "include");
18465 $Name = $Parts[$_].$SLASH.$Name;
18466 }
18467 }
18468}
18469
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018470sub detectSystemHeaders()
18471{
18472 my @SysHeaders = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018473 foreach my $DevelPath (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018474 {
18475 next if(not -d $DevelPath);
18476 # search for all header files in the /usr/include
18477 # with or without extension (ncurses.h, QtCore, ...)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018478 push(@SysHeaders, cmd_find($DevelPath,"f"));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018479 foreach my $Link (cmd_find($DevelPath,"l"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018480 { # add symbolic links
18481 if(-f $Link) {
18482 push(@SysHeaders, $Link);
18483 }
18484 }
18485 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018486 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018487 { # search for config headers in the /usr/lib
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018488 next if(not -d $DevelPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018489 foreach (cmd_find($DevelPath,"f",'\.h(pp|xx)?\Z|\/include\/',"",1))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018490 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018491 if(/\/(gcc|jvm|syslinux|kbd|parrot|xemacs)/)
18492 { # skip useless headers
18493 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018494 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018495 push(@SysHeaders, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018496 }
18497 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018498 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018499}
18500
18501sub detectSystemObjects()
18502{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018503 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018504 {
18505 next if(not -d $DevelPath);
18506 foreach my $Path (find_libs($DevelPath,"",""))
18507 { # search for shared libraries in the /usr/lib (including symbolic links)
18508 $SystemObjects{parse_libname(get_filename($Path), "name+ext", $OStarget)}{$Path}=1;
18509 }
18510 }
18511}
18512
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018513sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018514{
18515 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018516 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018517 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
18518 {
18519 if(not -e $Dest) {
18520 exitStatus("Access_Error", "can't access \'$Dest\'");
18521 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018522 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018523 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
18524 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018525 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018526 }
18527 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018528 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018529}
18530
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018531sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018532{
18533 my ($Path, $LibVersion) = @_;
18534 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018535 my $Name = get_filename($Path);
18536 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018537 return 1;
18538 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018539 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018540 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
18541 return 1;
18542 }
18543 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
18544 {
18545 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
18546 return 1;
18547 }
18548 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018549 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018550 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018551 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018552 return 1;
18553 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018554 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018555 return 1;
18556 }
18557 }
18558 return 0;
18559}
18560
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018561sub specificHeader($$)
18562{
18563 my ($Header, $Spec) = @_;
18564 my $Name = get_filename($Header);
18565
18566 if($Spec eq "windows")
18567 {# MS Windows
18568 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
18569 return 1 if($Name=~/([._-]w|win)(32|64)/i);
18570 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
18571 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
18572 my @Dirs = (
18573 "win32",
18574 "win64",
18575 "win",
18576 "windows",
18577 "msvcrt"
18578 ); # /gsf-win32/
18579 if(my $DIRs = join("|", @Dirs)) {
18580 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
18581 }
18582 }
18583 elsif($Spec eq "macos")
18584 { # Mac OS
18585 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
18586 }
18587
18588 return 0;
18589}
18590
18591sub skipAlienHeader($)
18592{
18593 my $Path = $_[0];
18594 my $Name = get_filename($Path);
18595 my $Dir = get_dirname($Path);
18596
18597 if($Tolerance=~/2/)
18598 { # 2 - skip internal headers
18599 my @Terms = (
18600 "p",
18601 "priv",
18602 "int",
18603 "impl",
18604 "implementation",
18605 "internal",
18606 "private",
18607 "old",
18608 "compat",
18609 "debug",
18610 "test",
18611 "gen"
18612 );
18613
18614 my @Dirs = (
18615 "private",
18616 "priv",
18617 "port",
18618 "impl",
18619 "internal",
18620 "detail",
18621 "details",
18622 "old",
18623 "compat",
18624 "debug",
18625 "config",
18626 "compiler",
18627 "platform",
18628 "test"
18629 );
18630
18631 if(my $TERMs = join("|", @Terms)) {
18632 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
18633 }
18634 if(my $DIRs = join("|", @Dirs)) {
18635 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
18636 }
18637
18638 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
18639 }
18640
18641 if($Tolerance=~/1/)
18642 { # 1 - skip non-Linux headers
18643 if($OSgroup ne "windows")
18644 {
18645 if(specificHeader($Path, "windows")) {
18646 return 1;
18647 }
18648 }
18649 if($OSgroup ne "macos")
18650 {
18651 if(specificHeader($Path, "macos")) {
18652 return 1;
18653 }
18654 }
18655 }
18656
18657 # valid
18658 return 0;
18659}
18660
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018661sub skipHeader($$)
18662{
18663 my ($Path, $LibVersion) = @_;
18664 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018665 if(defined $Cache{"skipHeader"}{$Path}) {
18666 return $Cache{"skipHeader"}{$Path};
18667 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018668 if(defined $Tolerance and $Tolerance=~/1|2/)
18669 { # --tolerant
18670 if(skipAlienHeader($Path)) {
18671 return ($Cache{"skipHeader"}{$Path} = 1);
18672 }
18673 }
18674 if(not keys(%{$SkipHeaders{$LibVersion}})) {
18675 return 0;
18676 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018677 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
18678}
18679
18680sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018681{ # returns:
18682 # 1 - if header should NOT be included and checked
18683 # 2 - if header should NOT be included, but should be checked
18684 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018685 my $Name = get_filename($Path);
18686 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018687 return $Kind;
18688 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018689 foreach my $D (keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018690 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018691 if(index($Path, $D)!=-1)
18692 {
18693 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
18694 return $SkipHeaders{$LibVersion}{"Path"}{$D};
18695 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018696 }
18697 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018698 foreach my $P (keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018699 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018700 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
18701 {
18702 if($Name=~/$P/) {
18703 return $Kind;
18704 }
18705 if($P=~/[\/\\]/ and $Path=~/$P/) {
18706 return $Kind;
18707 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018708 }
18709 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018710
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018711 return 0;
18712}
18713
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018714sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018715{
18716 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018717 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018718 { # system directory
18719 return;
18720 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018721 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018722 { # already registered
18723 return;
18724 }
18725 foreach my $Path (find_libs($Dir,"",1))
18726 {
18727 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018728 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018729 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018730 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018731 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
18732}
18733
18734sub registerObject($$)
18735{
18736 my ($Path, $LibVersion) = @_;
18737 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018738 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Andrey Ponomarenko27681702012-11-12 16:33:39 +040018739 if($OSgroup=~/linux|bsd/i)
18740 {
18741 if(my $SONAME = getSONAME($Path)) {
18742 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
18743 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018744 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018745 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
18746 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018747 }
18748}
18749
18750sub getSONAME($)
18751{
18752 my $Path = $_[0];
18753 return if(not $Path);
18754 if(defined $Cache{"getSONAME"}{$Path}) {
18755 return $Cache{"getSONAME"}{$Path};
18756 }
18757 my $ObjdumpCmd = get_CmdPath("objdump");
18758 if(not $ObjdumpCmd) {
18759 exitStatus("Not_Found", "can't find \"objdump\"");
18760 }
18761 my $SonameCmd = "$ObjdumpCmd -x $Path 2>$TMP_DIR/null";
18762 if($OSgroup eq "windows") {
18763 $SonameCmd .= " | find \"SONAME\"";
18764 }
18765 else {
18766 $SonameCmd .= " | grep SONAME";
18767 }
18768 if(my $SonameInfo = `$SonameCmd`) {
18769 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
18770 return ($Cache{"getSONAME"}{$Path} = $1);
18771 }
18772 }
18773 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018774}
18775
18776sub getSOPaths_Dest($$)
18777{
18778 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018779 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018780 return ();
18781 }
18782 if(-f $Dest)
18783 {
18784 if(not parse_libname($Dest, "name", $OStarget)) {
18785 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
18786 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018787 registerObject($Dest, $LibVersion);
18788 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018789 return ($Dest);
18790 }
18791 elsif(-d $Dest)
18792 {
18793 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018794 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018795 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018796 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
18797 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018798 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018799 { # all files and symlinks that match the name of a library
18800 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
18801 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018802 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018803 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018804 }
18805 }
18806 }
18807 else
18808 { # search for all files and symlinks
18809 foreach my $Path (find_libs($Dest,"",""))
18810 {
18811 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018812 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018813 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018814 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018815 }
18816 if($OSgroup eq "macos")
18817 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018818 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018819 {
18820 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018821 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018822 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018823 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
18824 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018825 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018826 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018827 }
18828 }
18829 }
18830 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018831 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018832 }
18833 else {
18834 return ();
18835 }
18836}
18837
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018838sub isCyclical($$)
18839{
18840 my ($Stack, $Value) = @_;
18841 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018842}
18843
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018844sub detectWordSize()
18845{
18846 return "" if(not $GCC_PATH);
18847 if($Cache{"detectWordSize"}) {
18848 return $Cache{"detectWordSize"};
18849 }
18850 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018851 my $Defines = `$GCC_PATH -E -dD \"$TMP_DIR/empty.h\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018852 unlink("$TMP_DIR/empty.h");
18853 my $WSize = 0;
18854 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018855 { # GCC 4
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018856 $WSize = $1;
18857 }
18858 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018859 { # GCC 3
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018860 my $PTRDIFF = $1;
18861 if($PTRDIFF=~/long/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018862 $WSize = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018863 }
18864 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018865 $WSize = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018866 }
18867 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018868 if(not $WSize) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018869 exitStatus("Error", "can't check WORD size");
18870 }
18871 return ($Cache{"detectWordSize"} = $WSize);
18872}
18873
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040018874sub getWordSize($) {
18875 return $WORD_SIZE{$_[0]};
18876}
18877
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018878sub majorVersion($)
18879{
18880 my $V = $_[0];
18881 return 0 if(not $V);
18882 my @VParts = split(/\./, $V);
18883 return $VParts[0];
18884}
18885
18886sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018887{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018888 my ($V1, $V2) = @_;
18889 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018890 my @V1Parts = split(/\./, $V1);
18891 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018892 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
18893 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018894 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
18895 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
18896 }
18897 return -1 if($#V1Parts < $#V2Parts);
18898 return 1 if($#V1Parts > $#V2Parts);
18899 return 0;
18900}
18901
18902sub read_ABI_Dump($$)
18903{
18904 my ($LibVersion, $Path) = @_;
18905 return if(not $LibVersion or not -e $Path);
18906 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018907 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018908 { # input *.abi
18909 $FilePath = $Path;
18910 }
18911 else
18912 { # input *.abi.tar.gz
18913 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018914 if(not isDump_U($FilePath)) {
18915 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
18916 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018917 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018918
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018919 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040018920
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018921 my $Line = readLineNum($FilePath, 0);
18922 if($Line=~/xml/)
18923 { # XML format
18924 loadModule("XmlDump");
18925 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018926 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018927 else
18928 { # Perl Data::Dumper format (default)
18929 open(DUMP, $FilePath);
18930 local $/ = undef;
18931 my $Content = <DUMP>;
18932 close(DUMP);
18933
18934 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
18935 { # remove temp file
18936 unlink($FilePath);
18937 }
18938 if($Content!~/};\s*\Z/) {
18939 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
18940 }
18941 $ABI = eval($Content);
18942 if(not $ABI) {
18943 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
18944 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018945 }
18946 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018947 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018948 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018949 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018950 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018951 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018952 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018953 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018954
18955 if($ABI->{"ABI_DUMP_VERSION"})
18956 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018957 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018958 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018959 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018960 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018961 }
18962 else
18963 { # support for old ABI dumps
18964 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018965 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018966 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018967 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018968 }
18969 if(majorVersion($DVersion)<2)
18970 { # support for old ABI dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018971 if($UseOldDumps)
18972 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018973 if(cmpVersions($DVersion, $OLDEST_SUPPORTED_VERSION)<0) {
18974 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (older than $OLDEST_SUPPORTED_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018975 }
18976 }
18977 else
18978 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018979 my $Msg = "incompatible version \'$DVersion\' of specified ABI dump (allowed only 2.0<=V<=$ABI_DUMP_VERSION)";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018980 if(cmpVersions($DVersion, $OLDEST_SUPPORTED_VERSION)>=0) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018981 $Msg .= "\nUse -old-dumps option to use old-version dumps ($OLDEST_SUPPORTED_VERSION<=V<2.0)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018982 }
18983 exitStatus("Dump_Version", $Msg);
18984 }
18985 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018986
18987 if(defined $ABI->{"ABI_DUMPER_VERSION"})
18988 { # DWARF ABI Dump
18989 $UseConv_Real{$LibVersion}{"P"} = 1;
18990 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
18991
18992 $UsedDump{$LibVersion}{"DWARF"} = 1;
18993
18994 $TargetComponent = "module";
18995 }
18996
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040018997 if(not checkDump($LibVersion, "2.11"))
18998 { # old ABI dumps
18999 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019000 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019001 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019002 { # ABI dump created with --binary option
19003 $UsedDump{$LibVersion}{"BinOnly"} = 1;
19004 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019005 else
19006 { # default
19007 $UsedDump{$LibVersion}{"SrcBin"} = 1;
19008 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019009
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019010 if(defined $ABI->{"Mode"}
19011 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019012 { # --ext option
19013 $ExtendedCheck = 1;
19014 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019015 if($ABI->{"Extra"}) {
19016 $ExtraDump = 1;
19017 }
19018
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019019 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019020 {
19021 $UsedDump{$LibVersion}{"L"} = $Lang;
19022 setLanguage($LibVersion, $Lang);
19023 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019024 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019025 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019026 }
19027 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019028 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019029 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019030 if(not $TInfo)
19031 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019032 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019033 }
19034 my %Tid_TDid = ();
19035 foreach my $TDid (keys(%{$TInfo}))
19036 {
19037 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
19038 {
19039 $MAX_ID = $Tid if($Tid>$MAX_ID);
19040 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
19041 $Tid_TDid{$Tid}{$TDid}=1;
19042 }
19043 }
19044 my %NewID = ();
19045 foreach my $Tid (keys(%Tid_TDid))
19046 {
19047 my @TDids = keys(%{$Tid_TDid{$Tid}});
19048 if($#TDids>=1)
19049 {
19050 foreach my $TDid (@TDids)
19051 {
19052 if($TDid) {
19053 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19054 }
19055 else
19056 {
19057 if(my $ID = ++$MAX_ID)
19058 {
19059 $NewID{$TDid}{$Tid} = $ID;
19060 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
19061 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
19062 }
19063 }
19064 }
19065 }
19066 else
19067 {
19068 my $TDid = $TDids[0];
19069 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19070 }
19071 }
19072 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
19073 {
19074 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
19075 if(defined $Info{"BaseType"})
19076 {
19077 my $Bid = $Info{"BaseType"}{"Tid"};
19078 my $BDid = $Info{"BaseType"}{"TDid"};
19079 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019080 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019081 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
19082 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
19083 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019084 }
19085 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
19086 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019087 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019088 read_Machine_DumpInfo($ABI, $LibVersion);
19089 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019090 if(not $SymbolInfo{$LibVersion})
19091 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019092 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019093 }
19094 if(not keys(%{$SymbolInfo{$LibVersion}}))
19095 { # validation of old-version dumps
19096 if(not $ExtendedCheck) {
19097 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
19098 }
19099 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019100 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019101 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019102 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019103 else
19104 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019105 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019106 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019107 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019108 }
19109 if(not $DepSymbols)
19110 { # Cannot reconstruct DepSymbols. This may result in false
19111 # positives if the old dump is for library 2. Not a problem if
19112 # old dumps are only from old libraries.
19113 $DepSymbols = {};
19114 }
19115 foreach my $Symbol (keys(%{$DepSymbols})) {
19116 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
19117 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019118 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019119 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
19120 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
19121 $SkipTypes{$LibVersion} = $ABI->{"SkipTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019122 if(not $SkipTypes{$LibVersion})
19123 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019124 $SkipTypes{$LibVersion} = $ABI->{"OpaqueTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019125 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019126 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019127 if(not $SkipSymbols{$LibVersion})
19128 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019129 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019130 }
19131 if(not $SkipSymbols{$LibVersion})
19132 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019133 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019134 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019135 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
19136 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
19137 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019138 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019139 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019140 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019141 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019142 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019143 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019144 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019145 if(not checkDump($LibVersion, "2.10.1")
19146 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019147 { # support for old ABI dumps: added target headers
19148 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
19149 $TargetHeaders{$LibVersion}{get_filename($_)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019150 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019151 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
19152 $TargetHeaders{$LibVersion}{get_filename($_)}=1;
19153 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019154 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019155 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019156 if(defined $ABI->{"GccConstants"})
19157 { # 3.0
19158 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
19159 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
19160 }
19161 }
19162
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019163 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019164 if(not $NestedNameSpaces{$LibVersion})
19165 { # support for old dumps
19166 # Cannot reconstruct NameSpaces. This may affect design
19167 # of the compatibility report.
19168 $NestedNameSpaces{$LibVersion} = {};
19169 }
19170 # target system type
19171 # needed to adopt HTML report
19172 if(not $DumpSystem)
19173 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019174 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019175 }
19176 # recreate environment
19177 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
19178 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019179 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019180 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019181 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19182 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019183 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019184 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019185 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019186 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19187 {
19188 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19189 setLanguage($LibVersion, "C++");
19190 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019191 }
19192 }
19193 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019194 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
19195 {
19196 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
19197 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19198 }
19199 }
19200
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019201 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019202 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019203 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019204 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019205 {
19206 if(not $Symbol_Library{$LibVersion}{$MnglName}
19207 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
19208 push(@VFunc, $MnglName);
19209 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019210 }
19211 }
19212 translateSymbols(@VFunc, $LibVersion);
19213 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019214 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
19215
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019216 if(not checkDump($LibVersion, "3.0"))
19217 { # support for old ABI dumps
19218 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
19219 {
19220 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
19221 {
19222 if(ref($BaseType) eq "HASH") {
19223 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
19224 }
19225 }
19226 }
19227 }
19228
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019229 if(not checkDump($LibVersion, "2.20"))
19230 { # support for old ABI dumps
19231 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
19232 {
19233 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
19234
19235 if($TType=~/Struct|Union|Enum|Typedef/)
19236 { # repair complex types first
19237 next;
19238 }
19239
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019240 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019241 {
19242 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
19243 if($BType=~/Struct|Union|Enum/i)
19244 {
19245 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
19246 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
19247 }
19248 }
19249 }
19250 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
19251 {
19252 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
19253 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
19254 if($TType=~/Struct|Union|Enum/) {
19255 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
19256 }
19257 }
19258 }
19259
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019260 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019261 { # order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019262 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
19263 { # support for old ABI dumps < 2.0 (ACC 1.22)
19264 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
19265 {
19266 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
19267 {
19268 if($Access ne "public") {
19269 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
19270 }
19271 }
19272 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
19273 }
19274 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
19275 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019276 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
19277 { # support for old ABI dumps
19278 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
19279 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019280 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
19281 { # DWARF ABI Dumps
19282 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
19283 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019284 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
19285 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
19286 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019287 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
19288 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019289 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019290 foreach (keys(%{$TInfo{"Base"}})) {
19291 $Class_SubClasses{$LibVersion}{$_}{$TypeId}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019292 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019293 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019294 if($TInfo{"Type"} eq "MethodPtr")
19295 {
19296 if(defined $TInfo{"Param"})
19297 { # support for old ABI dumps <= 1.17
19298 if(not defined $TInfo{"Param"}{"0"})
19299 {
19300 my $Max = keys(%{$TInfo{"Param"}});
19301 foreach my $Pos (1 .. $Max) {
19302 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
19303 }
19304 delete($TInfo{"Param"}{$Max});
19305 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
19306 }
19307 }
19308 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019309 if($TInfo{"BaseType"} eq $TypeId)
19310 { # fix ABI dump
19311 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
19312 }
19313 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019314 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019315 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019316 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019317 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
19318 if(not $BName)
19319 { # broken type
19320 next;
19321 }
19322 if($TInfo{"Name"} eq $BName)
19323 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019324 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019325 next;
19326 }
19327 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
19328 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019329 }
19330 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019331 }
19332 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
19333 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019334 $TName_Tid{$LibVersion}{formatName($TInfo{"Name"}, "T")} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019335 }
19336 }
19337
19338 if(not checkDump($LibVersion, "2.15"))
19339 { # support for old ABI dumps
19340 my %Dups = ();
19341 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
19342 {
19343 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019344 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019345 if(not defined $TypeInfo{$LibVersion}{$ClassId})
19346 { # remove template decls
19347 delete($SymbolInfo{$LibVersion}{$InfoId});
19348 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019349 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019350 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040019351 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
19352 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019353 { # templates
19354 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019355 }
19356 }
19357 }
19358
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019359 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
19360 {
19361 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
19362 { # ABI dumps have no mangled names for C-functions
19363 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
19364 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019365 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
19366 { # support for old ABI dumps
19367 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
19368 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019369 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
19370 { # DWARF ABI Dumps
19371 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
19372 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019373 }
19374
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019375 $Descriptor{$LibVersion}{"Dump"} = 1;
19376}
19377
19378sub read_Machine_DumpInfo($$)
19379{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019380 my ($ABI, $LibVersion) = @_;
19381 if($ABI->{"Arch"}) {
19382 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019383 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019384 if($ABI->{"WordSize"}) {
19385 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019386 }
19387 else
19388 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019389 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019390 }
19391 if(not $WORD_SIZE{$LibVersion})
19392 { # support for old dumps (<1.23)
19393 if(my $Tid = getTypeIdByName("char*", $LibVersion))
19394 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019395 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019396 }
19397 else
19398 {
19399 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019400 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019401 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019402 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
19403 { # any "pointer"-type
19404 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019405 last;
19406 }
19407 }
19408 if($PSize)
19409 { # a pointer type size
19410 $WORD_SIZE{$LibVersion} = $PSize;
19411 }
19412 else {
19413 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
19414 }
19415 }
19416 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019417 if($ABI->{"GccVersion"}) {
19418 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019419 }
19420}
19421
19422sub read_Libs_DumpInfo($$)
19423{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019424 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019425 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
19426 if(not $Library_Symbol{$LibVersion})
19427 { # support for old dumps
19428 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
19429 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019430 if(keys(%{$Library_Symbol{$LibVersion}})
19431 and not $DumpAPI) {
19432 $Descriptor{$LibVersion}{"Libs"} = "OK";
19433 }
19434}
19435
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019436sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019437{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019438 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019439
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019440 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019441 and not $DumpAPI) {
19442 $Descriptor{$LibVersion}{"Headers"} = "OK";
19443 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019444 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019445 { # headers info is stored in the old dumps in the different way
19446 if($UseOldDumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019447 and my $Name = $ABI->{"Headers"}{$Identity}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019448 { # support for old dumps: headers info corrected in 1.22
19449 $Identity = $Name;
19450 }
19451 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019452 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019453 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019454
19455 if(keys(%{$ABI->{"Sources"}})
19456 and not $DumpAPI) {
19457 $Descriptor{$LibVersion}{"Sources"} = "OK";
19458 }
19459 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
19460 { # headers info is stored in the old dumps in the different way
19461 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
19462 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
19463 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019464}
19465
19466sub find_libs($$$)
19467{
19468 my ($Path, $Type, $MaxDepth) = @_;
19469 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019470 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019471}
19472
19473sub createDescriptor($$)
19474{
19475 my ($LibVersion, $Path) = @_;
19476 if(not $LibVersion or not $Path
19477 or not -e $Path) {
19478 return "";
19479 }
19480 if(-d $Path)
19481 { # directory with headers files and shared objects
19482 return "
19483 <version>
19484 ".$TargetVersion{$LibVersion}."
19485 </version>
19486
19487 <headers>
19488 $Path
19489 </headers>
19490
19491 <libs>
19492 $Path
19493 </libs>";
19494 }
19495 else
19496 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019497 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019498 { # standard XML-descriptor
19499 return readFile($Path);
19500 }
19501 elsif(is_header($Path, 2, $LibVersion))
19502 { # header file
19503 return "
19504 <version>
19505 ".$TargetVersion{$LibVersion}."
19506 </version>
19507
19508 <headers>
19509 $Path
19510 </headers>
19511
19512 <libs>
19513 none
19514 </libs>";
19515 }
19516 elsif(parse_libname($Path, "name", $OStarget))
19517 { # shared object
19518 return "
19519 <version>
19520 ".$TargetVersion{$LibVersion}."
19521 </version>
19522
19523 <headers>
19524 none
19525 </headers>
19526
19527 <libs>
19528 $Path
19529 </libs>";
19530 }
19531 else
19532 { # standard XML-descriptor
19533 return readFile($Path);
19534 }
19535 }
19536}
19537
19538sub detect_lib_default_paths()
19539{
19540 my %LPaths = ();
19541 if($OSgroup eq "bsd")
19542 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019543 if(my $LdConfig = get_CmdPath("ldconfig"))
19544 {
19545 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
19546 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019547 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
19548 {
19549 my $Name = "lib".$1;
19550 if(not defined $LPaths{$Name}) {
19551 $LPaths{$Name} = $2;
19552 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019553 }
19554 }
19555 }
19556 else {
19557 printMsg("WARNING", "can't find ldconfig");
19558 }
19559 }
19560 else
19561 {
19562 if(my $LdConfig = get_CmdPath("ldconfig"))
19563 {
19564 if($SystemRoot and $OSgroup eq "linux")
19565 { # use host (x86) ldconfig with the target (arm) ld.so.conf
19566 if(-e $SystemRoot."/etc/ld.so.conf") {
19567 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
19568 }
19569 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019570 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
19571 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019572 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
19573 {
19574 my ($Name, $Path) = ($1, $2);
19575 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019576 if(not defined $LPaths{$Name})
19577 { # get first element from the list of available paths
19578
19579 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
19580 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
19581 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
19582
19583 $LPaths{$Name} = $Path;
19584 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019585 }
19586 }
19587 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040019588 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019589 printMsg("WARNING", "can't find ldconfig");
19590 }
19591 }
19592 return \%LPaths;
19593}
19594
19595sub detect_bin_default_paths()
19596{
19597 my $EnvPaths = $ENV{"PATH"};
19598 if($OSgroup eq "beos") {
19599 $EnvPaths.=":".$ENV{"BETOOLS"};
19600 }
19601 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019602 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019603 {
19604 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019605 next if(not $Path);
19606 if($SystemRoot
19607 and $Path=~/\A\Q$SystemRoot\E\//)
19608 { # do NOT use binaries from target system
19609 next;
19610 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019611 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019612 }
19613}
19614
19615sub detect_inc_default_paths()
19616{
19617 return () if(not $GCC_PATH);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019618 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019619 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019620 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019621 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019622 next if(index($Line, "/cc1plus ")!=-1);
19623
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019624 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
19625 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019626 my $Path = realpath($1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019627 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019628 if(index($Path, "c++")!=-1
19629 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019630 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019631 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019632 if(not defined $MAIN_CPP_DIR
19633 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
19634 $MAIN_CPP_DIR = $Path;
19635 }
19636 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019637 elsif(index($Path, "gcc")!=-1) {
19638 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019639 }
19640 else
19641 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019642 if($Path=~/local[\/\\]+include/)
19643 { # local paths
19644 next;
19645 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019646 if($SystemRoot
19647 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
19648 { # The GCC include path for user headers is not a part of the system root
19649 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
19650 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
19651 next;
19652 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019653 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019654 }
19655 }
19656 }
19657 unlink("$TMP_DIR/empty.h");
19658 return %DPaths;
19659}
19660
19661sub detect_default_paths($)
19662{
19663 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
19664 my $Search = $_[0];
19665 if($Search!~/inc/) {
19666 $HSearch = 0;
19667 }
19668 if($Search!~/lib/) {
19669 $LSearch = 0;
19670 }
19671 if($Search!~/bin/) {
19672 $BSearch = 0;
19673 }
19674 if($Search!~/gcc/) {
19675 $GSearch = 0;
19676 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019677 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019678 { # <search_headers> section of the XML descriptor
19679 # do NOT search for systems headers
19680 $HSearch = 0;
19681 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019682 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019683 { # <search_headers> section of the XML descriptor
19684 # do NOT search for systems headers
19685 $LSearch = 0;
19686 }
19687 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
19688 { # additional search paths
19689 next if($Type eq "include" and not $HSearch);
19690 next if($Type eq "lib" and not $LSearch);
19691 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019692 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019693 }
19694 if($OSgroup ne "windows")
19695 { # unix-like
19696 foreach my $Type ("include", "lib", "bin")
19697 { # automatic detection of system "devel" directories
19698 next if($Type eq "include" and not $HSearch);
19699 next if($Type eq "lib" and not $LSearch);
19700 next if($Type eq "bin" and not $BSearch);
19701 my ($UsrDir, $RootDir) = ("/usr", "/");
19702 if($SystemRoot and $Type ne "bin")
19703 { # 1. search for target headers and libraries
19704 # 2. use host commands: ldconfig, readelf, etc.
19705 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
19706 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019707 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019708 if(-d $RootDir."/".$Type)
19709 { # if "/lib" is symbolic link
19710 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019711 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019712 }
19713 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019714 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019715 }
19716 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019717 if(-d $UsrDir)
19718 {
19719 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019720 if(-d $UsrDir."/".$Type)
19721 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019722 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019723 }
19724 }
19725 }
19726 }
19727 if($BSearch)
19728 {
19729 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019730 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019731 }
19732 # check environment variables
19733 if($OSgroup eq "beos")
19734 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019735 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019736 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019737 if($_ eq ".") {
19738 next;
19739 }
19740 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
19741 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
19742 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019743 }
19744 }
19745 if($HSearch)
19746 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019747 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
19748 split(/:|;/, $ENV{"BEINCLUDES"})
19749 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019750 }
19751 if($LSearch)
19752 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019753 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
19754 split(/:|;/, $ENV{"BELIBRARIES"}),
19755 split(/:|;/, $ENV{"LIBRARY_PATH"})
19756 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019757 }
19758 }
19759 if($LSearch)
19760 { # using linker to get system paths
19761 if(my $LPaths = detect_lib_default_paths())
19762 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019763 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019764 foreach my $Name (keys(%{$LPaths}))
19765 {
19766 if($SystemRoot
19767 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
19768 { # wrong ldconfig configuration
19769 # check your <sysroot>/etc/ld.so.conf
19770 next;
19771 }
19772 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019773 if(my $Dir = get_dirname($LPaths->{$Name})) {
19774 $Dirs{$Dir} = 1;
19775 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019776 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019777 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019778 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019779 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019780 }
19781 if($BSearch)
19782 {
19783 if($CrossGcc)
19784 { # --cross-gcc=arm-linux-gcc
19785 if(-e $CrossGcc)
19786 { # absolute or relative path
19787 $GCC_PATH = get_abs_path($CrossGcc);
19788 }
19789 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
19790 { # command name
19791 $GCC_PATH = $CrossGcc;
19792 }
19793 else {
19794 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
19795 }
19796 if($GCC_PATH=~/\s/) {
19797 $GCC_PATH = "\"".$GCC_PATH."\"";
19798 }
19799 }
19800 }
19801 if($GSearch)
19802 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019803 if(not $CrossGcc)
19804 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019805 $GCC_PATH = get_CmdPath("gcc");
19806 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019807 if(not $GCC_PATH)
19808 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019809 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019810 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019811 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019812 { # select the latest version
19813 @GCCs = sort {$b cmp $a} @GCCs;
19814 if(check_gcc($GCCs[0], "3"))
19815 {
19816 $GCC_PATH = $GCCs[0];
19817 last;
19818 }
19819 }
19820 }
19821 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019822 if(not $GCC_PATH) {
19823 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
19824 }
19825 if(not $CheckObjectsOnly_Opt)
19826 {
19827 if(my $GCC_Ver = get_dumpversion($GCC_PATH))
19828 {
19829 my $GccTarget = get_dumpmachine($GCC_PATH);
19830 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget)");
19831 if($GccTarget=~/symbian/)
19832 {
19833 $OStarget = "symbian";
19834 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
19835 }
19836 }
19837 else {
19838 exitStatus("Error", "something is going wrong with the GCC compiler");
19839 }
19840 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019841 if($HSearch)
19842 {
19843 if(not $NoStdInc)
19844 { # do NOT search in GCC standard paths
19845 my %DPaths = detect_inc_default_paths();
19846 @DefaultCppPaths = @{$DPaths{"Cpp"}};
19847 @DefaultGccPaths = @{$DPaths{"Gcc"}};
19848 @DefaultIncPaths = @{$DPaths{"Inc"}};
19849 push_U($SystemPaths{"include"}, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019850 }
19851 }
19852 }
19853 if($HSearch)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019854 { # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019855 my $IncPath = "/usr/include";
19856 if($SystemRoot) {
19857 $IncPath = $SystemRoot.$IncPath;
19858 }
19859 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019860 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019861 }
19862 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019863
19864 if($ExtraInfo)
19865 {
19866 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
19867 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
19868 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019869}
19870
19871sub getLIB_EXT($)
19872{
19873 my $Target = $_[0];
19874 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
19875 return $Ext;
19876 }
19877 return $OS_LibExt{$LIB_TYPE}{"default"};
19878}
19879
19880sub getAR_EXT($)
19881{
19882 my $Target = $_[0];
19883 if(my $Ext = $OS_Archive{$Target}) {
19884 return $Ext;
19885 }
19886 return $OS_Archive{"default"};
19887}
19888
19889sub get_dumpversion($)
19890{
19891 my $Cmd = $_[0];
19892 return "" if(not $Cmd);
19893 if($Cache{"get_dumpversion"}{$Cmd}) {
19894 return $Cache{"get_dumpversion"}{$Cmd};
19895 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019896 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019897 chomp($V);
19898 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
19899}
19900
19901sub get_dumpmachine($)
19902{
19903 my $Cmd = $_[0];
19904 return "" if(not $Cmd);
19905 if($Cache{"get_dumpmachine"}{$Cmd}) {
19906 return $Cache{"get_dumpmachine"}{$Cmd};
19907 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019908 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019909 chomp($Machine);
19910 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
19911}
19912
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019913sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019914{
19915 my $Cmd = $_[0];
19916 return "" if(not $Cmd);
19917 my @Options = (
19918 "--version",
19919 "-help"
19920 );
19921 foreach my $Opt (@Options)
19922 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019923 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019924 if($Info) {
19925 return 1;
19926 }
19927 }
19928 return 0;
19929}
19930
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019931sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019932{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019933 my ($Cmd, $ReqVer) = @_;
19934 return 0 if(not $Cmd or not $ReqVer);
19935 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
19936 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019937 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019938 if(my $GccVer = get_dumpversion($Cmd))
19939 {
19940 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
19941 if(cmpVersions($GccVer, $ReqVer)>=0) {
19942 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
19943 }
19944 }
19945 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019946}
19947
19948sub get_depth($)
19949{
19950 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019951 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019952 }
19953 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
19954}
19955
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019956sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019957{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019958 return if($Cache{"registerGccHeaders"}); # this function should be called once
19959
19960 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019961 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019962 my @Headers = cmd_find($Path,"f");
19963 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
19964 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019965 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019966 my $FileName = get_filename($HPath);
19967 if(not defined $DefaultGccHeader{$FileName})
19968 { # skip duplicated
19969 $DefaultGccHeader{$FileName} = $HPath;
19970 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019971 }
19972 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019973 $Cache{"registerGccHeaders"} = 1;
19974}
19975
19976sub registerCppHeaders()
19977{
19978 return if($Cache{"registerCppHeaders"}); # this function should be called once
19979
19980 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019981 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019982 my @Headers = cmd_find($CppDir,"f");
19983 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
19984 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019985 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019986 my $FileName = get_filename($Path);
19987 if(not defined $DefaultCppHeader{$FileName})
19988 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019989 $DefaultCppHeader{$FileName} = $Path;
19990 }
19991 }
19992 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019993 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019994}
19995
19996sub parse_libname($$$)
19997{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019998 return "" if(not $_[0]);
19999 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
20000 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020001 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020002 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
20003}
20004
20005sub parse_libname_I($$$)
20006{
20007 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020008
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020009 if($Target eq "symbian") {
20010 return parse_libname_symbian($Name, $Type);
20011 }
20012 elsif($Target eq "windows") {
20013 return parse_libname_windows($Name, $Type);
20014 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020015
20016 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020017 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020018 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020019 { # libSDL-1.2.so.0.7.1
20020 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020021 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020022 if($Type eq "name")
20023 { # libSDL-1.2
20024 # libwbxml2
20025 return $2;
20026 }
20027 elsif($Type eq "name+ext")
20028 { # libSDL-1.2.so
20029 # libwbxml2.so
20030 return $1;
20031 }
20032 elsif($Type eq "version")
20033 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020034 if(defined $7
20035 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020036 { # 0.7.1
20037 return $7;
20038 }
20039 else
20040 { # libc-2.5.so (=>2.5 version)
20041 my $MV = $5;
20042 $MV=~s/\A[\-\_]+//g;
20043 return $MV;
20044 }
20045 }
20046 elsif($Type eq "short")
20047 { # libSDL
20048 # libwbxml2
20049 return $3;
20050 }
20051 elsif($Type eq "shortest")
20052 { # SDL
20053 # wbxml
20054 return shortest_name($3);
20055 }
20056 }
20057 return "";# error
20058}
20059
20060sub parse_libname_symbian($$)
20061{
20062 my ($Name, $Type) = @_;
20063 my $Ext = getLIB_EXT("symbian");
20064 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
20065 { # libpthread{00010001}.dso
20066 if($Type eq "name")
20067 { # libpthread{00010001}
20068 return $2;
20069 }
20070 elsif($Type eq "name+ext")
20071 { # libpthread{00010001}.dso
20072 return $1;
20073 }
20074 elsif($Type eq "version")
20075 { # 00010001
20076 my $V = $4;
20077 $V=~s/\{(.+)\}/$1/;
20078 return $V;
20079 }
20080 elsif($Type eq "short")
20081 { # libpthread
20082 return $3;
20083 }
20084 elsif($Type eq "shortest")
20085 { # pthread
20086 return shortest_name($3);
20087 }
20088 }
20089 return "";# error
20090}
20091
20092sub parse_libname_windows($$)
20093{
20094 my ($Name, $Type) = @_;
20095 my $Ext = getLIB_EXT("windows");
20096 if($Name=~/((.+?)\.$Ext)\Z/)
20097 { # netapi32.dll
20098 if($Type eq "name")
20099 { # netapi32
20100 return $2;
20101 }
20102 elsif($Type eq "name+ext")
20103 { # netapi32.dll
20104 return $1;
20105 }
20106 elsif($Type eq "version")
20107 { # DLL version embedded
20108 # at binary-level
20109 return "";
20110 }
20111 elsif($Type eq "short")
20112 { # netapi32
20113 return $2;
20114 }
20115 elsif($Type eq "shortest")
20116 { # netapi
20117 return shortest_name($2);
20118 }
20119 }
20120 return "";# error
20121}
20122
20123sub shortest_name($)
20124{
20125 my $Name = $_[0];
20126 # remove prefix
20127 $Name=~s/\A(lib|open)//;
20128 # remove suffix
20129 $Name=~s/[\W\d_]+\Z//i;
20130 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
20131 return $Name;
20132}
20133
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020134sub createSymbolsList($$$$$)
20135{
20136 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
20137 read_ABI_Dump(1, $DPath);
20138 if(not $CheckObjectsOnly) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020139 prepareSymbols(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020140 }
20141 my %SymbolHeaderLib = ();
20142 my $Total = 0;
20143 # Get List
20144 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
20145 {
20146 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020147 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020148 next;
20149 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020150 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020151 { # skip other symbols
20152 next;
20153 }
20154 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
20155 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020156 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020157 next;
20158 }
20159 my $DyLib = $Symbol_Library{1}{$Symbol};
20160 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020161 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020162 next;
20163 }
20164 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
20165 $Total+=1;
20166 }
20167 # Draw List
20168 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
20169 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
20170 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
20171 {
20172 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
20173 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020174 my %NS_Symbol = ();
20175 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020176 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020177 }
20178 foreach my $NameSpace (sort keys(%NS_Symbol))
20179 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020180 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020181 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
20182 foreach my $Symbol (@SortedInterfaces)
20183 {
20184 my $SubReport = "";
20185 my $Signature = get_Signature($Symbol, 1);
20186 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020187 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020188 }
20189 if($Symbol=~/\A(_Z|\?)/)
20190 {
20191 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020192 $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 +040020193 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020194 else {
20195 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
20196 }
20197 }
20198 else
20199 {
20200 if($Signature) {
20201 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
20202 }
20203 else {
20204 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
20205 }
20206 }
20207 $SYMBOLS_LIST .= $SubReport;
20208 }
20209 }
20210 $SYMBOLS_LIST .= "<br/>\n";
20211 }
20212 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020213 # clear info
20214 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
20215 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
20216 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
20217 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020218 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020219 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020220 my $CssStyles = readModule("Styles", "SymbolsList.css");
20221 my $JScripts = readModule("Scripts", "Sections.js");
20222 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020223 my $Title = "$LName: public symbols";
20224 my $Keywords = "$LName, API, symbols";
20225 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020226 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020227 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020228 <br/><br/><hr/>\n".getReportFooter($LName, 1)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020229 <div style='height:999px;'></div></body></html>";
20230 writeFile($SaveTo, $SYMBOLS_LIST);
20231}
20232
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020233sub add_target_libs($)
20234{
20235 foreach (@{$_[0]}) {
20236 $TargetLibs{$_} = 1;
20237 }
20238}
20239
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020240sub is_target_lib($)
20241{
20242 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020243 if(not $LName) {
20244 return 0;
20245 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020246 if($TargetLibraryName
20247 and $LName!~/\Q$TargetLibraryName\E/) {
20248 return 0;
20249 }
20250 if(keys(%TargetLibs)
20251 and not $TargetLibs{$LName}
20252 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
20253 return 0;
20254 }
20255 return 1;
20256}
20257
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020258sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020259{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020260 my ($H, $V) = @_;
20261 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020262 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020263 if($TargetHeaders{$V}{$H}) {
20264 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020265 }
20266 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020267 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020268}
20269
20270sub checkVersionNum($$)
20271{
20272 my ($LibVersion, $Path) = @_;
20273 if(my $VerNum = $TargetVersion{$LibVersion}) {
20274 return $VerNum;
20275 }
20276 my $UsedAltDescr = 0;
20277 foreach my $Part (split(/\s*,\s*/, $Path))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020278 { # try to get version string from file path
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020279 next if(isDump($Part)); # ABI dump
20280 next if($Part=~/\.(xml|desc)\Z/i); # XML descriptor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020281 my $VerNum = "";
20282 if(parse_libname($Part, "name", $OStarget))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020283 {
20284 $UsedAltDescr = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020285 $VerNum = parse_libname($Part, "version", $OStarget);
20286 if(not $VerNum) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040020287 $VerNum = readStrVer($Part);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020288 }
20289 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020290 elsif(is_header($Part, 2, $LibVersion) or -d $Part)
20291 {
20292 $UsedAltDescr = 1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040020293 $VerNum = readStrVer($Part);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020294 }
20295 if($VerNum ne "")
20296 {
20297 $TargetVersion{$LibVersion} = $VerNum;
20298 if($DumpAPI) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020299 printMsg("WARNING", "setting version number to $VerNum (use -vnum option to change it)");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020300 }
20301 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020302 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 +040020303 }
20304 return $TargetVersion{$LibVersion};
20305 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020306 }
20307 if($UsedAltDescr)
20308 {
20309 if($DumpAPI) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020310 exitStatus("Error", "version number is not set (use -vnum option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020311 }
20312 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020313 exitStatus("Error", ($LibVersion==1?"1st":"2nd")." version number is not set (use -v$LibVersion option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020314 }
20315 }
20316}
20317
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040020318sub readStrVer($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020319{
20320 my $Str = $_[0];
20321 return "" if(not $Str);
20322 $Str=~s/\Q$TargetLibraryName\E//g;
20323 if($Str=~/(\/|\\|\w|\A)[\-\_]*(\d+[\d\.\-]+\d+|\d+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020324 { # .../libssh-0.4.0/...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020325 return $2;
20326 }
20327 elsif(my $V = parse_libname($Str, "version", $OStarget)) {
20328 return $V;
20329 }
20330 return "";
20331}
20332
20333sub readLibs($)
20334{
20335 my $LibVersion = $_[0];
20336 if($OStarget eq "windows")
20337 { # dumpbin.exe will crash
20338 # without VS Environment
20339 check_win32_env();
20340 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020341 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020342 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020343 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020344}
20345
20346sub dump_sorting($)
20347{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040020348 my $Hash = $_[0];
20349 return [] if(not $Hash);
20350 my @Keys = keys(%{$Hash});
20351 return [] if($#Keys<0);
20352 if($Keys[0]=~/\A\d+\Z/)
20353 { # numbers
20354 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020355 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040020356 else
20357 { # strings
20358 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020359 }
20360}
20361
20362sub printMsg($$)
20363{
20364 my ($Type, $Msg) = @_;
20365 if($Type!~/\AINFO/) {
20366 $Msg = $Type.": ".$Msg;
20367 }
20368 if($Type!~/_C\Z/) {
20369 $Msg .= "\n";
20370 }
20371 if($Quiet)
20372 { # --quiet option
20373 appendFile($COMMON_LOG_PATH, $Msg);
20374 }
20375 else
20376 {
20377 if($Type eq "ERROR") {
20378 print STDERR $Msg;
20379 }
20380 else {
20381 print $Msg;
20382 }
20383 }
20384}
20385
20386sub exitStatus($$)
20387{
20388 my ($Code, $Msg) = @_;
20389 printMsg("ERROR", $Msg);
20390 exit($ERROR_CODE{$Code});
20391}
20392
20393sub exitReport()
20394{ # the tool has run without any errors
20395 printReport();
20396 if($COMPILE_ERRORS)
20397 { # errors in headers may add false positives/negatives
20398 exit($ERROR_CODE{"Compile_Error"});
20399 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020400 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
20401 { # --binary
20402 exit($ERROR_CODE{"Incompatible"});
20403 }
20404 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
20405 { # --source
20406 exit($ERROR_CODE{"Incompatible"});
20407 }
20408 elsif($RESULT{"Source"}{"Problems"}
20409 or $RESULT{"Binary"}{"Problems"})
20410 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020411 exit($ERROR_CODE{"Incompatible"});
20412 }
20413 else {
20414 exit($ERROR_CODE{"Compatible"});
20415 }
20416}
20417
20418sub readRules($)
20419{
20420 my $Kind = $_[0];
20421 if(not -f $RULES_PATH{$Kind}) {
20422 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
20423 }
20424 my $Content = readFile($RULES_PATH{$Kind});
20425 while(my $Rule = parseTag(\$Content, "rule"))
20426 {
20427 my $RId = parseTag(\$Rule, "id");
20428 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
20429 foreach my $Prop (@Properties) {
20430 if(my $Value = parseTag(\$Rule, lc($Prop)))
20431 {
20432 $Value=~s/\n[ ]*//;
20433 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
20434 }
20435 }
20436 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
20437 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
20438 }
20439 else {
20440 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
20441 }
20442 }
20443}
20444
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020445sub getReportPath($)
20446{
20447 my $Level = $_[0];
20448 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
20449 if($Level eq "Binary")
20450 {
20451 if($BinaryReportPath)
20452 { # --bin-report-path
20453 return $BinaryReportPath;
20454 }
20455 elsif($OutputReportPath)
20456 { # --report-path
20457 return $OutputReportPath;
20458 }
20459 else
20460 { # default
20461 return $Dir."/abi_compat_report.$ReportFormat";
20462 }
20463 }
20464 elsif($Level eq "Source")
20465 {
20466 if($SourceReportPath)
20467 { # --src-report-path
20468 return $SourceReportPath;
20469 }
20470 elsif($OutputReportPath)
20471 { # --report-path
20472 return $OutputReportPath;
20473 }
20474 else
20475 { # default
20476 return $Dir."/src_compat_report.$ReportFormat";
20477 }
20478 }
20479 else
20480 {
20481 if($OutputReportPath)
20482 { # --report-path
20483 return $OutputReportPath;
20484 }
20485 else
20486 { # default
20487 return $Dir."/compat_report.$ReportFormat";
20488 }
20489 }
20490}
20491
20492sub printStatMsg($)
20493{
20494 my $Level = $_[0];
20495 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
20496}
20497
20498sub listAffected($)
20499{
20500 my $Level = $_[0];
20501 my $List = "";
20502 foreach (keys(%{$TotalAffected{$Level}}))
20503 {
20504 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
20505 { # skip "Low"-severity problems
20506 next;
20507 }
20508 $List .= "$_\n";
20509 }
20510 my $Dir = get_dirname(getReportPath($Level));
20511 if($Level eq "Binary") {
20512 writeFile($Dir."/abi_affected.txt", $List);
20513 }
20514 elsif($Level eq "Source") {
20515 writeFile($Dir."/src_affected.txt", $List);
20516 }
20517}
20518
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020519sub printReport()
20520{
20521 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020522 createReport();
20523 if($JoinReport or $DoubleReport)
20524 {
20525 if($RESULT{"Binary"}{"Problems"}
20526 or $RESULT{"Source"}{"Problems"}) {
20527 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020528 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020529 else {
20530 printMsg("INFO", "result: COMPATIBLE");
20531 }
20532 printStatMsg("Binary");
20533 printStatMsg("Source");
20534 if($ListAffected)
20535 { # --list-affected
20536 listAffected("Binary");
20537 listAffected("Source");
20538 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020539 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020540 elsif($BinaryOnly)
20541 {
20542 if($RESULT{"Binary"}{"Problems"}) {
20543 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
20544 }
20545 else {
20546 printMsg("INFO", "result: COMPATIBLE");
20547 }
20548 printStatMsg("Binary");
20549 if($ListAffected)
20550 { # --list-affected
20551 listAffected("Binary");
20552 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020553 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020554 elsif($SourceOnly)
20555 {
20556 if($RESULT{"Source"}{"Problems"}) {
20557 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
20558 }
20559 else {
20560 printMsg("INFO", "result: COMPATIBLE");
20561 }
20562 printStatMsg("Source");
20563 if($ListAffected)
20564 { # --list-affected
20565 listAffected("Source");
20566 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020567 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020568 if($StdOut)
20569 {
20570 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040020571 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020572 printMsg("INFO", "compatibility report has been generated to stdout");
20573 }
20574 else
20575 { # default
20576 printMsg("INFO", "compatibility reports have been generated to stdout");
20577 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020578 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020579 else
20580 {
20581 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040020582 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020583 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
20584 }
20585 elsif($DoubleReport)
20586 { # default
20587 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
20588 }
20589 elsif($BinaryOnly)
20590 { # --binary
20591 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
20592 }
20593 elsif($SourceOnly)
20594 { # --source
20595 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
20596 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020597 }
20598}
20599
20600sub check_win32_env()
20601{
20602 if(not $ENV{"DevEnvDir"}
20603 or not $ENV{"LIB"}) {
20604 exitStatus("Error", "can't start without VS environment (vsvars32.bat)");
20605 }
20606}
20607
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020608sub diffSets($$)
20609{
20610 my ($S1, $S2) = @_;
20611 my @SK1 = keys(%{$S1});
20612 my @SK2 = keys(%{$S2});
20613 if($#SK1!=$#SK2) {
20614 return 1;
20615 }
20616 foreach my $K1 (@SK1)
20617 {
20618 if(not defined $S2->{$K1}) {
20619 return 1;
20620 }
20621 }
20622 return 0;
20623}
20624
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020625sub create_ABI_Dump()
20626{
20627 if(not -e $DumpAPI) {
20628 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
20629 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020630 my @DParts = split(/\s*,\s*/, $DumpAPI);
20631 foreach my $Part (@DParts)
20632 {
20633 if(not -e $Part) {
20634 exitStatus("Access_Error", "can't access \'$Part\'");
20635 }
20636 }
20637 checkVersionNum(1, $DumpAPI);
20638 foreach my $Part (@DParts)
20639 {
20640 if(isDump($Part)) {
20641 read_ABI_Dump(1, $Part);
20642 }
20643 else {
20644 readDescriptor(1, createDescriptor(1, $Part));
20645 }
20646 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020647
20648 if(not $Descriptor{1}{"Version"})
20649 { # set to default: X
20650 $Descriptor{1}{"Version"} = "X";
20651 }
20652
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020653 initLogging(1);
20654 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020655
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020656 my $DumpPath = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{1}{"Version"}.".abi";
20657 $DumpPath .= ".".$AR_EXT; # gzipped by default
20658 if($OutputDumpPath)
20659 { # user defined path
20660 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020661 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020662 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
20663
20664 if(not $Archive and not $StdOut)
20665 { # check archive utilities
20666 if($OSgroup eq "windows")
20667 { # using zip
20668 my $ZipCmd = get_CmdPath("zip");
20669 if(not $ZipCmd) {
20670 exitStatus("Not_Found", "can't find \"zip\"");
20671 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020672 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020673 else
20674 { # using tar and gzip
20675 my $TarCmd = get_CmdPath("tar");
20676 if(not $TarCmd) {
20677 exitStatus("Not_Found", "can't find \"tar\"");
20678 }
20679 my $GzipCmd = get_CmdPath("gzip");
20680 if(not $GzipCmd) {
20681 exitStatus("Not_Found", "can't find \"gzip\"");
20682 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020683 }
20684 }
20685
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020686 if(not $Descriptor{1}{"Dump"})
20687 {
20688 if(not $CheckHeadersOnly) {
20689 readLibs(1);
20690 }
20691 if($CheckHeadersOnly) {
20692 setLanguage(1, "C++");
20693 }
20694 if(not $CheckObjectsOnly) {
20695 searchForHeaders(1);
20696 }
20697 $WORD_SIZE{1} = detectWordSize();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020698 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020699 if(not $Descriptor{1}{"Dump"})
20700 {
20701 if($Descriptor{1}{"Headers"}) {
20702 readHeaders(1);
20703 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020704 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020705 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020706 if(not keys(%{$SymbolInfo{1}}))
20707 { # check if created dump is valid
20708 if(not $ExtendedCheck and not $CheckObjectsOnly)
20709 {
20710 if($CheckHeadersOnly) {
20711 exitStatus("Empty_Set", "the set of public symbols is empty");
20712 }
20713 else {
20714 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
20715 }
20716 }
20717 }
20718 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020719 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020720 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
20721 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020722 if($ExtraDump)
20723 { # add unmangled names to the ABI dump
20724 my @Names = ();
20725 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
20726 {
20727 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
20728 push(@Names, $MnglName);
20729 }
20730 }
20731 translateSymbols(@Names, 1);
20732 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
20733 {
20734 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
20735 {
20736 if(my $Unmangled = $tr_name{$MnglName})
20737 {
20738 if($MnglName ne $Unmangled) {
20739 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
20740 }
20741 }
20742 }
20743 }
20744 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020745
20746 my %GccConstants = (); # built-in GCC constants
20747 foreach my $Name (keys(%{$Constants{1}}))
20748 {
20749 if(not defined $Constants{1}{$Name}{"Header"})
20750 {
20751 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
20752 delete($Constants{1}{$Name});
20753 }
20754 }
20755
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020756 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020757 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020758 "TypeInfo" => $TypeInfo{1},
20759 "SymbolInfo" => $SymbolInfo{1},
20760 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020761 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020762 "SymbolVersion" => $SymVer{1},
20763 "LibraryVersion" => $Descriptor{1}{"Version"},
20764 "LibraryName" => $TargetLibraryName,
20765 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020766 "SkipTypes" => $SkipTypes{1},
20767 "SkipSymbols" => $SkipSymbols{1},
20768 "SkipNameSpaces" => $SkipNameSpaces{1},
20769 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020770 "Headers" => \%HeadersInfo,
20771 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020772 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020773 "NameSpaces" => $NestedNameSpaces{1},
20774 "Target" => $OStarget,
20775 "Arch" => getArch(1),
20776 "WordSize" => $WORD_SIZE{1},
20777 "GccVersion" => get_dumpversion($GCC_PATH),
20778 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
20779 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
20780 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020781 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020782 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020783 }
20784 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020785 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020786 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020787 if($ExtendedCheck)
20788 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020789 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020790 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020791 if($BinaryOnly)
20792 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020793 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020794 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020795 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020796 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020797 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020798 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
20799 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020800 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020801
20802 my $ABI_DUMP = "";
20803 if($UseXML)
20804 {
20805 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020806 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020807 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020808 else
20809 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020810 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020811 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020812 if($StdOut)
20813 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020814 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020815 printMsg("INFO", "ABI dump has been generated to stdout");
20816 return;
20817 }
20818 else
20819 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020820 my ($DDir, $DName) = separate_path($DumpPath);
20821 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020822 if(not $Archive) {
20823 $DPath = $DumpPath;
20824 }
20825
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020826 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020827
20828 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020829 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020830 close(DUMP);
20831
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020832 if(not -s $DPath) {
20833 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
20834 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040020835 if($Archive) {
20836 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020837 }
20838
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040020839 if(not $OutputDumpPath)
20840 {
20841 printMsg("INFO", "library ABI has been dumped to:\n $DumpPath");
20842 printMsg("INFO", "you can transfer this dump everywhere and use instead of the ".$Descriptor{1}{"Version"}." version descriptor");
20843 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020844 }
20845}
20846
20847sub quickEmptyReports()
20848{ # Quick "empty" reports
20849 # 4 times faster than merging equal dumps
20850 # NOTE: the dump contains the "LibraryVersion" attribute
20851 # if you change the version, then your dump will be different
20852 # OVERCOME: use -v1 and v2 options for comparing dumps
20853 # and don't change version in the XML descriptor (and dumps)
20854 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
20855 if(-s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
20856 {
20857 my $FilePath1 = unpackDump($Descriptor{1}{"Path"});
20858 my $FilePath2 = unpackDump($Descriptor{2}{"Path"});
20859 if($FilePath1 and $FilePath2)
20860 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020861 my $Line = readLineNum($FilePath1, 0);
20862 if($Line=~/xml/)
20863 { # XML format
20864 # is not supported yet
20865 return;
20866 }
20867
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020868 local $/ = undef;
20869
20870 open(DUMP1, $FilePath1);
20871 my $Content1 = <DUMP1>;
20872 close(DUMP1);
20873
20874 open(DUMP2, $FilePath2);
20875 my $Content2 = <DUMP2>;
20876 close(DUMP2);
20877
20878 if($Content1 eq $Content2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020879 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020880 # clean memory
20881 undef $Content2;
20882
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020883 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020884 my $ABIdump = eval($Content1);
20885
20886 # clean memory
20887 undef $Content1;
20888
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020889 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020890 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 +040020891 }
20892 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020893 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020894 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
20895 }
20896 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020897 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020898 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
20899 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020900 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020901 read_Libs_DumpInfo($ABIdump, 1);
20902 read_Machine_DumpInfo($ABIdump, 1);
20903 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020904
20905 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
20906 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
20907
20908 %{$CheckedSymbols{"Binary"}} = %{$ABIdump->{"SymbolInfo"}};
20909 %{$CheckedSymbols{"Source"}} = %{$ABIdump->{"SymbolInfo"}};
20910
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020911 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
20912 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
20913 exitReport();
20914 }
20915 }
20916 }
20917}
20918
20919sub initLogging($)
20920{
20921 my $LibVersion = $_[0];
20922 # create log directory
20923 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
20924 if($OutputLogPath{$LibVersion})
20925 { # user-defined by -log-path option
20926 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
20927 }
20928 if($LogMode ne "n") {
20929 mkpath($LOG_DIR);
20930 }
20931 $LOG_PATH{$LibVersion} = get_abs_path($LOG_DIR)."/".$LOG_FILE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020932 if($Debug)
20933 { # debug directory
20934 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020935
20936 if(not $ExtraInfo)
20937 { # enable --extra-info
20938 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
20939 }
20940
20941 # enable --extra-dump
20942 $ExtraDump = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020943 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040020944 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020945}
20946
20947sub writeLog($$)
20948{
20949 my ($LibVersion, $Msg) = @_;
20950 if($LogMode ne "n") {
20951 appendFile($LOG_PATH{$LibVersion}, $Msg);
20952 }
20953}
20954
20955sub resetLogging($)
20956{
20957 my $LibVersion = $_[0];
20958 if($LogMode!~/a|n/)
20959 { # remove old log
20960 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040020961 if($Debug) {
20962 rmtree($DEBUG_PATH{$LibVersion});
20963 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020964 }
20965}
20966
20967sub printErrorLog($)
20968{
20969 my $LibVersion = $_[0];
20970 if($LogMode ne "n") {
20971 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
20972 }
20973}
20974
20975sub isDump($)
20976{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020977 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz|\.zip|\.xml|)(\.\w+|)\Z/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020978 return $1;
20979 }
20980 return 0;
20981}
20982
20983sub isDump_U($)
20984{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020985 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)(\.\w+|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020986 return $1;
20987 }
20988 return 0;
20989}
20990
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020991sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020992{
20993 # read input XML descriptors or ABI dumps
20994 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040020995 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020996 }
20997 my @DParts1 = split(/\s*,\s*/, $Descriptor{1}{"Path"});
20998 foreach my $Part (@DParts1)
20999 {
21000 if(not -e $Part) {
21001 exitStatus("Access_Error", "can't access \'$Part\'");
21002 }
21003 }
21004 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021005 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021006 }
21007 my @DParts2 = split(/\s*,\s*/, $Descriptor{2}{"Path"});
21008 foreach my $Part (@DParts2)
21009 {
21010 if(not -e $Part) {
21011 exitStatus("Access_Error", "can't access \'$Part\'");
21012 }
21013 }
21014 detect_default_paths("bin"); # to extract dumps
21015 if($#DParts1==0 and $#DParts2==0
21016 and isDump($Descriptor{1}{"Path"})
21017 and isDump($Descriptor{2}{"Path"}))
21018 { # optimization: equal ABI dumps
21019 quickEmptyReports();
21020 }
21021 checkVersionNum(1, $Descriptor{1}{"Path"});
21022 checkVersionNum(2, $Descriptor{2}{"Path"});
21023 printMsg("INFO", "preparation, please wait ...");
21024 foreach my $Part (@DParts1)
21025 {
21026 if(isDump($Part)) {
21027 read_ABI_Dump(1, $Part);
21028 }
21029 else {
21030 readDescriptor(1, createDescriptor(1, $Part));
21031 }
21032 }
21033 foreach my $Part (@DParts2)
21034 {
21035 if(isDump($Part)) {
21036 read_ABI_Dump(2, $Part);
21037 }
21038 else {
21039 readDescriptor(2, createDescriptor(2, $Part));
21040 }
21041 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021042
21043 if(not $Descriptor{1}{"Version"})
21044 { # set to default: X
21045 $Descriptor{1}{"Version"} = "X";
21046 }
21047
21048 if(not $Descriptor{2}{"Version"})
21049 { # set to default: Y
21050 $Descriptor{2}{"Version"} = "Y";
21051 }
21052
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021053 initLogging(1);
21054 initLogging(2);
21055 # check consistency
21056 if(not $Descriptor{1}{"Headers"}
21057 and not $Descriptor{1}{"Libs"}) {
21058 exitStatus("Error", "descriptor d1 does not contain both header files and libraries info");
21059 }
21060 if(not $Descriptor{2}{"Headers"}
21061 and not $Descriptor{2}{"Libs"}) {
21062 exitStatus("Error", "descriptor d2 does not contain both header files and libraries info");
21063 }
21064 if($Descriptor{1}{"Headers"} and not $Descriptor{1}{"Libs"}
21065 and not $Descriptor{2}{"Headers"} and $Descriptor{2}{"Libs"}) {
21066 exitStatus("Error", "can't compare headers with $SLIB_TYPE libraries");
21067 }
21068 elsif(not $Descriptor{1}{"Headers"} and $Descriptor{1}{"Libs"}
21069 and $Descriptor{2}{"Headers"} and not $Descriptor{2}{"Libs"}) {
21070 exitStatus("Error", "can't compare $SLIB_TYPE libraries with headers");
21071 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021072 if(not $Descriptor{1}{"Headers"})
21073 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021074 if($CheckHeadersOnly_Opt) {
21075 exitStatus("Error", "can't find header files info in descriptor d1");
21076 }
21077 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021078 if(not $Descriptor{2}{"Headers"})
21079 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021080 if($CheckHeadersOnly_Opt) {
21081 exitStatus("Error", "can't find header files info in descriptor d2");
21082 }
21083 }
21084 if(not $Descriptor{1}{"Headers"}
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021085 or not $Descriptor{2}{"Headers"})
21086 {
21087 if(not $CheckObjectsOnly_Opt)
21088 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021089 printMsg("WARNING", "comparing $SLIB_TYPE libraries only");
21090 $CheckObjectsOnly = 1;
21091 }
21092 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021093 if(not $Descriptor{1}{"Libs"})
21094 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021095 if($CheckObjectsOnly_Opt) {
21096 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d1");
21097 }
21098 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021099 if(not $Descriptor{2}{"Libs"})
21100 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021101 if($CheckObjectsOnly_Opt) {
21102 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d2");
21103 }
21104 }
21105 if(not $Descriptor{1}{"Libs"}
21106 or not $Descriptor{2}{"Libs"})
21107 { # comparing standalone header files
21108 # comparing ABI dumps created with --headers-only
21109 if(not $CheckHeadersOnly_Opt)
21110 {
21111 printMsg("WARNING", "checking headers only");
21112 $CheckHeadersOnly = 1;
21113 }
21114 }
21115 if($UseDumps)
21116 { # --use-dumps
21117 # parallel processing
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021118 my $DumpPath1 = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{1}{"Version"}.".abi.$AR_EXT";
21119 my $DumpPath2 = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{2}{"Version"}.".abi.$AR_EXT";
21120
21121 unlink($DumpPath1);
21122 unlink($DumpPath2);
21123
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021124 my $pid = fork();
21125 if($pid)
21126 { # dump on two CPU cores
21127 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
21128 if($RelativeDirectory{1}) {
21129 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
21130 }
21131 if($OutputLogPath{1}) {
21132 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
21133 }
21134 if($CrossGcc) {
21135 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
21136 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021137 if($Quiet)
21138 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021139 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021140 @PARAMS = (@PARAMS, "-logging-mode", "a");
21141 }
21142 elsif($LogMode and $LogMode ne "w")
21143 { # "w" is default
21144 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021145 }
21146 if($ExtendedCheck) {
21147 @PARAMS = (@PARAMS, "-extended");
21148 }
21149 if($UserLang) {
21150 @PARAMS = (@PARAMS, "-lang", $UserLang);
21151 }
21152 if($TargetVersion{1}) {
21153 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
21154 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021155 if($BinaryOnly) {
21156 @PARAMS = (@PARAMS, "-binary");
21157 }
21158 if($SourceOnly) {
21159 @PARAMS = (@PARAMS, "-source");
21160 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021161 if($SortDump) {
21162 @PARAMS = (@PARAMS, "-sort");
21163 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021164 if($DumpFormat and $DumpFormat ne "perl") {
21165 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
21166 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040021167 if($CheckHeadersOnly) {
21168 @PARAMS = (@PARAMS, "-headers-only");
21169 }
21170 if($CheckObjectsOnly) {
21171 @PARAMS = (@PARAMS, "-objects-only");
21172 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021173 if($Debug)
21174 {
21175 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021176 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021177 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021178 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021179 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021180 exit(1);
21181 }
21182 }
21183 else
21184 { # child
21185 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
21186 if($RelativeDirectory{2}) {
21187 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
21188 }
21189 if($OutputLogPath{2}) {
21190 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
21191 }
21192 if($CrossGcc) {
21193 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
21194 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021195 if($Quiet)
21196 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021197 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021198 @PARAMS = (@PARAMS, "-logging-mode", "a");
21199 }
21200 elsif($LogMode and $LogMode ne "w")
21201 { # "w" is default
21202 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021203 }
21204 if($ExtendedCheck) {
21205 @PARAMS = (@PARAMS, "-extended");
21206 }
21207 if($UserLang) {
21208 @PARAMS = (@PARAMS, "-lang", $UserLang);
21209 }
21210 if($TargetVersion{2}) {
21211 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
21212 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021213 if($BinaryOnly) {
21214 @PARAMS = (@PARAMS, "-binary");
21215 }
21216 if($SourceOnly) {
21217 @PARAMS = (@PARAMS, "-source");
21218 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021219 if($SortDump) {
21220 @PARAMS = (@PARAMS, "-sort");
21221 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021222 if($DumpFormat and $DumpFormat ne "perl") {
21223 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
21224 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040021225 if($CheckHeadersOnly) {
21226 @PARAMS = (@PARAMS, "-headers-only");
21227 }
21228 if($CheckObjectsOnly) {
21229 @PARAMS = (@PARAMS, "-objects-only");
21230 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021231 if($Debug)
21232 {
21233 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021234 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021235 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021236 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021237 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021238 exit(1);
21239 }
21240 else {
21241 exit(0);
21242 }
21243 }
21244 waitpid($pid, 0);
21245 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021246 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
21247 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021248 if($TargetLibraryFName ne $TargetLibraryName) {
21249 @CMP_PARAMS = (@CMP_PARAMS, "-l-full", $TargetLibraryFName);
21250 }
21251 if($ShowRetVal) {
21252 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
21253 }
21254 if($CrossGcc) {
21255 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
21256 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021257 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
21258 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021259 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021260 }
21261 if($ReportFormat and $ReportFormat ne "html")
21262 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021263 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
21264 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021265 if($OutputReportPath) {
21266 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
21267 }
21268 if($BinaryReportPath) {
21269 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
21270 }
21271 if($SourceReportPath) {
21272 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
21273 }
21274 if($LoggingPath) {
21275 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
21276 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040021277 if($CheckHeadersOnly) {
21278 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
21279 }
21280 if($CheckObjectsOnly) {
21281 @CMP_PARAMS = (@CMP_PARAMS, "-objects-only");
21282 }
21283 if($BinaryOnly) {
21284 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
21285 }
21286 if($SourceOnly) {
21287 @CMP_PARAMS = (@CMP_PARAMS, "-source");
21288 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021289 if($Browse) {
21290 @CMP_PARAMS = (@CMP_PARAMS, "-browse", $Browse);
21291 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021292 if($OpenReport) {
21293 @CMP_PARAMS = (@CMP_PARAMS, "-open");
21294 }
21295 if($Debug)
21296 {
21297 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
21298 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021299 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021300 system("perl", $0, @CMP_PARAMS);
21301 exit($?>>8);
21302 }
21303 if(not $Descriptor{1}{"Dump"}
21304 or not $Descriptor{2}{"Dump"})
21305 { # need GCC toolchain to analyze
21306 # header files and libraries
21307 detect_default_paths("inc|lib|gcc");
21308 }
21309 if(not $Descriptor{1}{"Dump"})
21310 {
21311 if(not $CheckHeadersOnly) {
21312 readLibs(1);
21313 }
21314 if($CheckHeadersOnly) {
21315 setLanguage(1, "C++");
21316 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021317 if(not $CheckObjectsOnly) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021318 searchForHeaders(1);
21319 }
21320 $WORD_SIZE{1} = detectWordSize();
21321 }
21322 if(not $Descriptor{2}{"Dump"})
21323 {
21324 if(not $CheckHeadersOnly) {
21325 readLibs(2);
21326 }
21327 if($CheckHeadersOnly) {
21328 setLanguage(2, "C++");
21329 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021330 if(not $CheckObjectsOnly) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021331 searchForHeaders(2);
21332 }
21333 $WORD_SIZE{2} = detectWordSize();
21334 }
21335 if($WORD_SIZE{1} ne $WORD_SIZE{2})
21336 { # support for old ABI dumps
21337 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021338 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021339 {
21340 $WORD_SIZE{1} = $WORD_SIZE{2};
21341 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
21342 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021343 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021344 {
21345 $WORD_SIZE{2} = $WORD_SIZE{1};
21346 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
21347 }
21348 }
21349 elsif(not $WORD_SIZE{1}
21350 and not $WORD_SIZE{2})
21351 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021352 $WORD_SIZE{1} = "4";
21353 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021354 }
21355 if($Descriptor{1}{"Dump"})
21356 { # support for old ABI dumps
21357 prepareTypes(1);
21358 }
21359 if($Descriptor{2}{"Dump"})
21360 { # support for old ABI dumps
21361 prepareTypes(2);
21362 }
21363 if($AppPath and not keys(%{$Symbol_Library{1}})) {
21364 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
21365 }
21366 # started to process input data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021367 if(not $CheckObjectsOnly)
21368 {
21369 if($Descriptor{1}{"Headers"}
21370 and not $Descriptor{1}{"Dump"}) {
21371 readHeaders(1);
21372 }
21373 if($Descriptor{2}{"Headers"}
21374 and not $Descriptor{2}{"Dump"}) {
21375 readHeaders(2);
21376 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021377 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021378
21379 # clean memory
21380 %SystemHeaders = ();
21381 %mangled_name_gcc = ();
21382
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021383 prepareSymbols(1);
21384 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021385
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021386 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021387 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021388
21389 # Virtual Tables
21390 registerVTable(1);
21391 registerVTable(2);
21392
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021393 if(not checkDump(1, "1.22")
21394 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021395 { # support for old ABI dumps
21396 foreach my $ClassName (keys(%{$VirtualTable{2}}))
21397 {
21398 if($ClassName=~/</)
21399 { # templates
21400 if(not defined $VirtualTable{1}{$ClassName})
21401 { # synchronize
21402 delete($VirtualTable{2}{$ClassName});
21403 }
21404 }
21405 }
21406 }
21407
21408 registerOverriding(1);
21409 registerOverriding(2);
21410
21411 setVirtFuncPositions(1);
21412 setVirtFuncPositions(2);
21413
21414 # Other
21415 addParamNames(1);
21416 addParamNames(2);
21417
21418 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021419}
21420
21421sub compareAPIs($)
21422{
21423 my $Level = $_[0];
21424 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040021425 loadModule("CallConv");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021426 if($Level eq "Binary") {
21427 printMsg("INFO", "comparing ABIs ...");
21428 }
21429 else {
21430 printMsg("INFO", "comparing APIs ...");
21431 }
21432 if($CheckHeadersOnly
21433 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021434 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021435 detectAdded_H($Level);
21436 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021437 }
21438 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021439 { # added/removed in libs
21440 detectAdded($Level);
21441 detectRemoved($Level);
21442 }
21443 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021444 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021445 mergeSymbols($Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021446 if(keys(%{$CheckedSymbols{$Level}})) {
21447 mergeConstants($Level);
21448 }
21449 }
21450 if($CheckHeadersOnly
21451 or $Level eq "Source")
21452 { # added/removed in headers
21453 mergeHeaders($Level);
21454 }
21455 else
21456 { # added/removed in libs
21457 mergeLibs($Level);
21458 if($CheckImpl
21459 and $Level eq "Binary") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021460 mergeImpl();
21461 }
21462 }
21463}
21464
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021465sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021466{
21467 my %Opts = (
21468 "OStarget"=>$OStarget,
21469 "Debug"=>$Debug,
21470 "Quiet"=>$Quiet,
21471 "LogMode"=>$LogMode,
21472 "CheckHeadersOnly"=>$CheckHeadersOnly,
21473
21474 "SystemRoot"=>$SystemRoot,
21475 "MODULES_DIR"=>$MODULES_DIR,
21476 "GCC_PATH"=>$GCC_PATH,
21477 "TargetSysInfo"=>$TargetSysInfo,
21478 "CrossPrefix"=>$CrossPrefix,
21479 "TargetLibraryName"=>$TargetLibraryName,
21480 "CrossGcc"=>$CrossGcc,
21481 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021482 "NoStdInc"=>$NoStdInc,
21483
21484 "BinaryOnly" => $BinaryOnly,
21485 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021486 );
21487 return \%Opts;
21488}
21489
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021490sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021491{
21492 my %CODE_ERROR = reverse(%ERROR_CODE);
21493 return $CODE_ERROR{$_[0]};
21494}
21495
21496sub scenario()
21497{
21498 if($StdOut)
21499 { # enable quiet mode
21500 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021501 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021502 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021503 if(not $LogMode)
21504 { # default
21505 $LogMode = "w";
21506 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021507 if($UserLang)
21508 { # --lang=C++
21509 $UserLang = uc($UserLang);
21510 $COMMON_LANGUAGE{1}=$UserLang;
21511 $COMMON_LANGUAGE{2}=$UserLang;
21512 }
21513 if($LoggingPath)
21514 {
21515 $OutputLogPath{1} = $LoggingPath;
21516 $OutputLogPath{2} = $LoggingPath;
21517 if($Quiet) {
21518 $COMMON_LOG_PATH = $LoggingPath;
21519 }
21520 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021521 if($OutputDumpPath)
21522 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021523 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021524 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
21525 }
21526 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021527 if($BinaryOnly and $SourceOnly)
21528 { # both --binary and --source
21529 # is the default mode
21530 $DoubleReport = 1;
21531 $JoinReport = 0;
21532 $BinaryOnly = 0;
21533 $SourceOnly = 0;
21534 if($OutputReportPath)
21535 { # --report-path
21536 $DoubleReport = 0;
21537 $JoinReport = 1;
21538 }
21539 }
21540 elsif($BinaryOnly or $SourceOnly)
21541 { # --binary or --source
21542 $DoubleReport = 0;
21543 $JoinReport = 0;
21544 }
21545 if($UseXML)
21546 { # --xml option
21547 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021548 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021549 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021550 if($ReportFormat)
21551 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021552 $ReportFormat = lc($ReportFormat);
21553 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021554 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021555 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021556 if($ReportFormat eq "htm")
21557 { # HTM == HTML
21558 $ReportFormat = "html";
21559 }
21560 elsif($ReportFormat eq "xml")
21561 { # --report-format=XML equal to --xml
21562 $UseXML = 1;
21563 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021564 }
21565 else
21566 { # default: HTML
21567 $ReportFormat = "html";
21568 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021569 if($DumpFormat)
21570 { # validate
21571 $DumpFormat = lc($DumpFormat);
21572 if($DumpFormat!~/\A(xml|perl)\Z/) {
21573 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
21574 }
21575 if($DumpFormat eq "xml")
21576 { # --dump-format=XML equal to --xml
21577 $UseXML = 1;
21578 }
21579 }
21580 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021581 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021582 $DumpFormat = "perl";
21583 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021584 if($Quiet and $LogMode!~/a|n/)
21585 { # --quiet log
21586 if(-f $COMMON_LOG_PATH) {
21587 unlink($COMMON_LOG_PATH);
21588 }
21589 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040021590 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021591 $CheckUndefined = 1;
21592 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021593 if($TestTool and $UseDumps)
21594 { # --test && --use-dumps == --test-dump
21595 $TestDump = 1;
21596 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021597 if($Tolerant)
21598 { # enable all
21599 $Tolerance = 1234;
21600 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021601 if($Help)
21602 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021603 HELP_MESSAGE();
21604 exit(0);
21605 }
21606 if($InfoMsg) {
21607 INFO_MESSAGE();
21608 exit(0);
21609 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021610 if($ShowVersion)
21611 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021612 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.");
21613 exit(0);
21614 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021615 if($DumpVersion)
21616 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021617 printMsg("INFO", $TOOL_VERSION);
21618 exit(0);
21619 }
21620 if($ExtendedCheck) {
21621 $CheckHeadersOnly = 1;
21622 }
21623 if($SystemRoot_Opt)
21624 { # user defined root
21625 if(not -e $SystemRoot_Opt) {
21626 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
21627 }
21628 $SystemRoot = $SystemRoot_Opt;
21629 $SystemRoot=~s/[\/]+\Z//g;
21630 if($SystemRoot) {
21631 $SystemRoot = get_abs_path($SystemRoot);
21632 }
21633 }
21634 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021635
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021636 if($SortDump)
21637 {
21638 $Data::Dumper::Useperl = 1;
21639 $Data::Dumper::Sortkeys = \&dump_sorting;
21640 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021641
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021642 if($TargetLibsPath)
21643 {
21644 if(not -f $TargetLibsPath) {
21645 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
21646 }
21647 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath))) {
21648 $TargetLibs{$Lib} = 1;
21649 }
21650 }
21651 if($TargetHeadersPath)
21652 { # --headers-list
21653 if(not -f $TargetHeadersPath) {
21654 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
21655 }
21656 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
21657 {
21658 $TargetHeaders{1}{$Header} = 1;
21659 $TargetHeaders{2}{$Header} = 1;
21660 }
21661 }
21662 if($TargetHeader)
21663 { # --header
21664 $TargetHeaders{1}{$TargetHeader} = 1;
21665 $TargetHeaders{2}{$TargetHeader} = 1;
21666 }
21667 if($TestTool
21668 or $TestDump)
21669 { # --test, --test-dump
21670 detect_default_paths("bin|gcc"); # to compile libs
21671 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040021672 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
21673 $LIB_EXT, $GCC_PATH, $Browse, $OpenReport, $SortDump, $CheckHeadersOnly, $CheckObjectsOnly);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021674 exit(0);
21675 }
21676 if($DumpSystem)
21677 { # --dump-system
21678 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021679 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021680 { # system XML descriptor
21681 if(not -f $DumpSystem) {
21682 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
21683 }
21684 my $Ret = readSystemDescriptor(readFile($DumpSystem));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021685 foreach (@{$Ret->{"Tools"}})
21686 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021687 push_U($SystemPaths{"bin"}, $_);
21688 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021689 }
21690 if($Ret->{"CrossPrefix"}) {
21691 $CrossPrefix = $Ret->{"CrossPrefix"};
21692 }
21693 }
21694 elsif($SystemRoot_Opt)
21695 { # -sysroot "/" option
21696 # default target: /usr/lib, /usr/include
21697 # search libs: /usr/lib and /lib
21698 if(not -e $SystemRoot."/usr/lib") {
21699 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
21700 }
21701 if(not -e $SystemRoot."/lib") {
21702 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
21703 }
21704 if(not -e $SystemRoot."/usr/include") {
21705 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
21706 }
21707 readSystemDescriptor("
21708 <name>
21709 $DumpSystem
21710 </name>
21711 <headers>
21712 $SystemRoot/usr/include
21713 </headers>
21714 <libs>
21715 $SystemRoot/usr/lib
21716 </libs>
21717 <search_libs>
21718 $SystemRoot/lib
21719 </search_libs>");
21720 }
21721 else {
21722 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
21723 }
21724 detect_default_paths("bin|gcc"); # to check symbols
21725 if($OStarget eq "windows")
21726 { # to run dumpbin.exe
21727 # and undname.exe
21728 check_win32_env();
21729 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021730 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021731 exit(0);
21732 }
21733 if($CmpSystems)
21734 { # --cmp-systems
21735 detect_default_paths("bin"); # to extract dumps
21736 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021737 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021738 exit(0);
21739 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021740 if($GenerateTemplate)
21741 {
21742 writeFile("VERSION.xml", $DescriptorTemplate."\n");
21743 printMsg("INFO", "XML-descriptor template ./VERSION.xml has been generated");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021744 exit(0);
21745 }
21746 if(not $TargetLibraryName) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021747 exitStatus("Error", "library name is not selected (-l option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021748 }
21749 else
21750 { # validate library name
21751 if($TargetLibraryName=~/[\*\/\\]/) {
21752 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
21753 }
21754 }
21755 if(not $TargetLibraryFName) {
21756 $TargetLibraryFName = $TargetLibraryName;
21757 }
21758 if($CheckHeadersOnly_Opt and $CheckObjectsOnly_Opt) {
21759 exitStatus("Error", "you can't specify both -headers-only and -objects-only options at the same time");
21760 }
21761 if($SymbolsListPath)
21762 {
21763 if(not -f $SymbolsListPath) {
21764 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
21765 }
21766 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
21767 $SymbolsList{$Interface} = 1;
21768 }
21769 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021770 if($SkipSymbolsListPath)
21771 {
21772 if(not -f $SkipSymbolsListPath) {
21773 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
21774 }
21775 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath))) {
21776 $SkipSymbolsList{$Interface} = 1;
21777 }
21778 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021779 if($SkipHeadersPath)
21780 {
21781 if(not -f $SkipHeadersPath) {
21782 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
21783 }
21784 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021785 { # register for both versions
21786 $SkipHeadersList{1}{$Path} = 1;
21787 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021788 my ($CPath, $Type) = classifyPath($Path);
21789 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021790 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021791 }
21792 }
21793 if($ParamNamesPath)
21794 {
21795 if(not -f $ParamNamesPath) {
21796 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
21797 }
21798 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
21799 {
21800 if($Line=~s/\A(\w+)\;//)
21801 {
21802 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021803 if($Line=~/;(\d+);/)
21804 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021805 while($Line=~s/(\d+);(\w+)//) {
21806 $AddIntParams{$Interface}{$1}=$2;
21807 }
21808 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021809 else
21810 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021811 my $Num = 0;
21812 foreach my $Name (split(/;/, $Line)) {
21813 $AddIntParams{$Interface}{$Num++}=$Name;
21814 }
21815 }
21816 }
21817 }
21818 }
21819 if($AppPath)
21820 {
21821 if(not -f $AppPath) {
21822 exitStatus("Access_Error", "can't access file \'$AppPath\'");
21823 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021824 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021825 $SymbolsList_App{$Interface} = 1;
21826 }
21827 }
21828 if($DumpAPI)
21829 { # --dump-abi
21830 # make an API dump
21831 create_ABI_Dump();
21832 exit($COMPILE_ERRORS);
21833 }
21834 # default: compare APIs
21835 # -d1 <path>
21836 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021837 compareInit();
21838 if($JoinReport or $DoubleReport)
21839 {
21840 compareAPIs("Binary");
21841 compareAPIs("Source");
21842 }
21843 elsif($BinaryOnly) {
21844 compareAPIs("Binary");
21845 }
21846 elsif($SourceOnly) {
21847 compareAPIs("Source");
21848 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021849 exitReport();
21850}
21851
21852scenario();