aboutsummaryrefslogtreecommitdiff
path: root/modules/Internals
diff options
context:
space:
mode:
authorAndrey Ponomarenko <aponomarenko@rosalab.ru>2012-03-11 11:57:02 +0400
committerAndrey Ponomarenko <aponomarenko@rosalab.ru>2012-03-11 11:57:02 +0400
commitab282100b2bf768a25be2a27675cd98e4e20f1d7 (patch)
treec251d91f14f566bfef9249f6c9635c893e641f7a /modules/Internals
parentb1c490a9b86ca77b32c462ee56d2a10cf66b2a31 (diff)
downloadabi-compliance-checker-ab282100b2bf768a25be2a27675cd98e4e20f1d7.tar.gz
ABI Compliance Checker 1.96.8
Diffstat (limited to 'modules/Internals')
-rw-r--r--modules/Internals/.svn/all-wcprops17
-rw-r--r--modules/Internals/.svn/entries99
-rw-r--r--modules/Internals/.svn/text-base/RegTests.pm.svn-base3961
-rw-r--r--modules/Internals/.svn/text-base/SysCheck.pm.svn-base1730
-rw-r--r--modules/Internals/RegTests.pm3961
-rw-r--r--modules/Internals/Styles/.svn/all-wcprops23
-rw-r--r--modules/Internals/Styles/.svn/entries130
-rw-r--r--modules/Internals/Styles/.svn/text-base/CmpSystems.css.svn-base62
-rw-r--r--modules/Internals/Styles/.svn/text-base/CompatReport.css.svn-base236
-rw-r--r--modules/Internals/Styles/.svn/text-base/SymbolsList.css.svn-base73
-rw-r--r--modules/Internals/Styles/CmpSystems.css62
-rw-r--r--modules/Internals/Styles/CompatReport.css236
-rw-r--r--modules/Internals/Styles/SymbolsList.css73
-rw-r--r--modules/Internals/SysCheck.pm1730
14 files changed, 12393 insertions, 0 deletions
diff --git a/modules/Internals/.svn/all-wcprops b/modules/Internals/.svn/all-wcprops
new file mode 100644
index 0000000..a44e6d9
--- /dev/null
+++ b/modules/Internals/.svn/all-wcprops
@@ -0,0 +1,17 @@
+K 25
+svn:wc:ra_dav:version-url
+V 63
+/svn/abi-compliance-checker/!svn/ver/65/trunk/modules/Internals
+END
+SysCheck.pm
+K 25
+svn:wc:ra_dav:version-url
+V 75
+/svn/abi-compliance-checker/!svn/ver/68/trunk/modules/Internals/SysCheck.pm
+END
+RegTests.pm
+K 25
+svn:wc:ra_dav:version-url
+V 75
+/svn/abi-compliance-checker/!svn/ver/65/trunk/modules/Internals/RegTests.pm
+END
diff --git a/modules/Internals/.svn/entries b/modules/Internals/.svn/entries
new file mode 100644
index 0000000..963d407
--- /dev/null
+++ b/modules/Internals/.svn/entries
@@ -0,0 +1,99 @@
+10
+
+dir
+67
+http://forge.ispras.ru/svn/abi-compliance-checker/trunk/modules/Internals
+http://forge.ispras.ru/svn/abi-compliance-checker
+
+
+
+2012-01-27T12:04:15.983802Z
+65
+aponomarenko
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+a821b6f2-9a20-4ec6-9ceb-7d4f98b805d9
+
+Styles
+dir
+
+SysCheck.pm
+file
+68
+
+
+
+2012-02-17T13:31:10.000000Z
+bbcc50bd96928abc91f2a57bd5ec5b5c
+2012-02-17T13:52:14.416803Z
+68
+aponomarenko
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+63026
+
+RegTests.pm
+file
+
+
+
+
+2012-01-27T07:43:35.000000Z
+bb1a9a9f4cbcc5388a3d5fe08fb15f11
+2012-01-27T12:04:15.983802Z
+65
+aponomarenko
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+126553
+
diff --git a/modules/Internals/.svn/text-base/RegTests.pm.svn-base b/modules/Internals/.svn/text-base/RegTests.pm.svn-base
new file mode 100644
index 0000000..20ff0aa
--- /dev/null
+++ b/modules/Internals/.svn/text-base/RegTests.pm.svn-base
@@ -0,0 +1,3961 @@
+###########################################################################
+# Internal Regression Tests for ABI Compliance Checker
+#
+# Copyright (C) 2009-2010 The Linux Foundation.
+# Copyright (C) 2009-2011 Institute for System Programming, RAS.
+# Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+# Copyright (C) 2011 ROSA Laboratory.
+#
+# Written by Andrey Ponomarenko
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License or the GNU Lesser
+# General Public License as published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# and the GNU Lesser General Public License along with this program.
+# If not, see <http://www.gnu.org/licenses/>.
+###########################################################################
+use strict;
+
+my ($TestDump, $Debug, $Quiet, $ExtendedCheck,
+$LogMode, $ReportFormat, $LIB_EXT, $GCC_PATH);
+my $OSgroup = get_OSgroup();
+
+sub testTool($$$$$$$$)
+{
+ ($TestDump, $Debug, $Quiet, $ExtendedCheck,
+ $LogMode, $ReportFormat, $LIB_EXT, $GCC_PATH) = @_;
+ testC();
+ testCpp();
+}
+
+sub testCpp()
+{
+ printMsg("INFO", "verifying detectable C++ library changes");
+ my ($HEADER1, $SOURCE1, $HEADER2, $SOURCE2) = ();
+ my $DECL_SPEC = ($OSgroup eq "windows")?"__declspec( dllexport )":"";
+ my $EXTERN = ($OSgroup eq "windows")?"extern ":"";# add "extern" for CL compiler
+
+ # Begin namespace
+ $HEADER1 .= "namespace TestNS {\n";
+ $HEADER2 .= "namespace TestNS {\n";
+ $SOURCE1 .= "namespace TestNS {\n";
+ $SOURCE2 .= "namespace TestNS {\n";
+
+ # Global_Data_Became_Const
+ $HEADER1 .= "
+ class $DECL_SPEC DataBecameConst {
+ public:
+ static int data;
+ };";
+ $SOURCE1 .= "
+ int DataBecameConst::data = 10;";
+
+ $HEADER2 .= "
+ class $DECL_SPEC DataBecameConst {
+ public:
+ static const int data;
+ };";
+ $SOURCE2 .= "
+ const int DataBecameConst::data = 10;";
+
+ # Global_Data_Became_Non_Const
+ $HEADER1 .= "
+ class $DECL_SPEC DataBecameNonConst {
+ public:
+ static const int data;
+ };";
+ $SOURCE1 .= "
+ const int DataBecameNonConst::data = 10;";
+
+ $HEADER2 .= "
+ class $DECL_SPEC DataBecameNonConst {
+ public:
+ static int data;
+ };";
+ $SOURCE2 .= "
+ int DataBecameNonConst::data = 10;";
+
+ # Parameter_Became_Restrict
+ $HEADER1 .= "
+ class $DECL_SPEC ParameterBecameRestrict {
+ public:
+ int method(int* param);
+ };";
+ $SOURCE1 .= "
+ int ParameterBecameRestrict::method(int* param) { return 0; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC ParameterBecameRestrict {
+ public:
+ int method(int* __restrict param);
+ };";
+ $SOURCE2 .= "
+ int ParameterBecameRestrict::method(int* __restrict param) { return 0; }";
+
+ # Field_Became_Volatile
+ $HEADER1 .= "
+ class $DECL_SPEC FieldBecameVolatile {
+ public:
+ int method(int param);
+ int f;
+ };";
+ $SOURCE1 .= "
+ int FieldBecameVolatile::method(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC FieldBecameVolatile {
+ public:
+ int method(int param);
+ volatile int f;
+ };";
+ $SOURCE2 .= "
+ int FieldBecameVolatile::method(int param) { return param; }";
+
+ # Method_Became_Const_Volatile
+ $HEADER1 .= "
+ class $DECL_SPEC MethodBecameConstVolatile {
+ public:
+ int method(int param);
+ };";
+ $SOURCE1 .= "
+ int MethodBecameConstVolatile::method(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC MethodBecameConstVolatile {
+ public:
+ int method(int param) volatile const;
+ };";
+ $SOURCE2 .= "
+ int MethodBecameConstVolatile::method(int param) volatile const { return param; }";
+
+ # Method_Became_Const
+ $HEADER1 .= "
+ class $DECL_SPEC MethodBecameConst {
+ public:
+ int method(int param);
+ };";
+ $SOURCE1 .= "
+ int MethodBecameConst::method(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC MethodBecameConst {
+ public:
+ int method(int param) const;
+ };";
+ $SOURCE2 .= "
+ int MethodBecameConst::method(int param) const { return param; }";
+
+ # Method_Became_Volatile
+ $HEADER1 .= "
+ class $DECL_SPEC MethodBecameVolatile {
+ public:
+ int method(int param);
+ };";
+ $SOURCE1 .= "
+ int MethodBecameVolatile::method(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC MethodBecameVolatile {
+ public:
+ int method(int param) volatile;
+ };";
+ $SOURCE2 .= "
+ int MethodBecameVolatile::method(int param) volatile { return param; }";
+
+ # Virtual_Method_Position (multiple bases)
+ $HEADER1 .= "
+ class $DECL_SPEC PrimaryBase
+ {
+ public:
+ virtual ~PrimaryBase();
+ virtual void foo();
+ };
+ class $DECL_SPEC SecondaryBase
+ {
+ public:
+ virtual ~SecondaryBase();
+ virtual void bar();
+ };
+ class UnsafeVirtualOverride: public PrimaryBase, public SecondaryBase
+ {
+ public:
+ UnsafeVirtualOverride();
+ ~UnsafeVirtualOverride();
+ void foo();
+ };";
+ $SOURCE1 .= "
+ PrimaryBase::~PrimaryBase() { }
+ void PrimaryBase::foo() { }
+
+ SecondaryBase::~SecondaryBase() { }
+ void SecondaryBase::bar() { }
+
+ UnsafeVirtualOverride::UnsafeVirtualOverride() { }
+ UnsafeVirtualOverride::~UnsafeVirtualOverride() { }
+ void UnsafeVirtualOverride::foo() { }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC PrimaryBase
+ {
+ public:
+ virtual ~PrimaryBase();
+ virtual void foo();
+ };
+ class $DECL_SPEC SecondaryBase
+ {
+ public:
+ virtual ~SecondaryBase();
+ virtual void bar();
+ };
+ class UnsafeVirtualOverride: public PrimaryBase, public SecondaryBase
+ {
+ public:
+ UnsafeVirtualOverride();
+ ~UnsafeVirtualOverride();
+ void foo();
+ void bar();
+ };";
+ $SOURCE2 .= "
+ PrimaryBase::~PrimaryBase() { }
+ void PrimaryBase::foo() { }
+
+ SecondaryBase::~SecondaryBase() { }
+ void SecondaryBase::bar() { }
+
+ UnsafeVirtualOverride::UnsafeVirtualOverride() { }
+ UnsafeVirtualOverride::~UnsafeVirtualOverride() { }
+ void UnsafeVirtualOverride::foo() { }
+ void UnsafeVirtualOverride::bar() { }";
+
+ # Removed_Interface (inline virtual d-tor)
+ $HEADER1 .= "
+ template <typename T>
+ class $DECL_SPEC BaseTemplate {
+ public:
+ BaseTemplate() { }
+ virtual int method(int param) { return param; };
+ virtual ~BaseTemplate() { };
+ };
+ class $DECL_SPEC RemovedVirtualDestructor: public BaseTemplate<int> {
+ public:
+ RemovedVirtualDestructor() { };
+ virtual int method2(int param);
+ };";
+ $SOURCE1 .= "
+ int RemovedVirtualDestructor::method2(int param) { return param; }";
+
+ $HEADER2 .= "
+ template <typename T>
+ class $DECL_SPEC BaseTemplate {
+ public:
+ BaseTemplate() { }
+ virtual int method(int param) { return param; };
+ //virtual ~BaseTemplate() { };
+ };
+ class $DECL_SPEC RemovedVirtualDestructor: public BaseTemplate<int> {
+ public:
+ RemovedVirtualDestructor() { };
+ virtual int method2(int param);
+ };";
+ $SOURCE2 .= "
+ int RemovedVirtualDestructor::method2(int param) { return param; }";
+
+ # Added_Virtual_Method_At_End
+ $HEADER1 .= "
+ class $DECL_SPEC DefaultConstructor {
+ public:
+ DefaultConstructor() { }
+ virtual int method(int param);
+ };";
+ $SOURCE1 .= "
+ int DefaultConstructor::method(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC DefaultConstructor {
+ public:
+ DefaultConstructor() { }
+ virtual int method(int param);
+ virtual int addedMethod(int param);
+ };";
+ $SOURCE2 .= "
+ int DefaultConstructor::method(int param) { return addedMethod(param); }
+ int DefaultConstructor::addedMethod(int param) { return param; }";
+
+ # Added_Enum_Member
+ $HEADER1 .= "
+ enum AddedEnumMember {
+ OldMember
+ };
+ $DECL_SPEC int addedEnumMember(enum AddedEnumMember param);";
+ $SOURCE1 .= "
+ int addedEnumMember(enum AddedEnumMember param) { return 0; }";
+
+ $HEADER2 .= "
+ enum AddedEnumMember {
+ OldMember,
+ NewMember
+ };
+ $DECL_SPEC int addedEnumMember(enum AddedEnumMember param);";
+ $SOURCE2 .= "
+ int addedEnumMember(enum AddedEnumMember param) { return 0; }";
+
+ # Parameter_Type_Format (Safe)
+ $HEADER1 .= "
+ struct DType
+ {
+ int i;
+ double j;
+ };
+ $DECL_SPEC int parameterTypeFormat(struct DType param);";
+ $SOURCE1 .= "
+ int parameterTypeFormat(struct DType param) { return 0; }";
+
+ $HEADER2 .= "
+ class DType
+ {
+ int i;
+ double j;
+ };
+ $DECL_SPEC int parameterTypeFormat(class DType param);";
+ $SOURCE2 .= "
+ int parameterTypeFormat(class DType param) { return 0; }";
+
+ # Removed_Virtual_Method (inline)
+ $HEADER1 .= "
+ class $DECL_SPEC RemovedInlineVirtualFunction {
+ public:
+ RemovedInlineVirtualFunction();
+ virtual int removedMethod(int param) { return 0; }
+ virtual int method(int param);
+ };";
+ $SOURCE1 .= "
+ int RemovedInlineVirtualFunction::method(int param) { return param; }
+ RemovedInlineVirtualFunction::RemovedInlineVirtualFunction() { }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC RemovedInlineVirtualFunction {
+ public:
+ RemovedInlineVirtualFunction();
+ virtual int method(int param);
+ };";
+ $SOURCE2 .= "
+ int RemovedInlineVirtualFunction::method(int param) { return param; }
+ RemovedInlineVirtualFunction::RemovedInlineVirtualFunction() { }";
+
+ # MethodPtr
+ $HEADER1 .= "
+ class TestMethodPtr {
+ public:
+ typedef void (TestMethodPtr::*Method)(int*);
+ Method _method;
+ TestMethodPtr();
+ void method();
+ };";
+ $SOURCE1 .= "
+ TestMethodPtr::TestMethodPtr() { }
+ void TestMethodPtr::method() { }";
+
+ $HEADER2 .= "
+ class TestMethodPtr {
+ public:
+ typedef void (TestMethodPtr::*Method)(int*, void*);
+ Method _method;
+ TestMethodPtr();
+ void method();
+ };";
+ $SOURCE2 .= "
+ TestMethodPtr::TestMethodPtr() { }
+ void TestMethodPtr::method() { }";
+
+ # FieldPtr
+ $HEADER1 .= "
+ class TestFieldPtr {
+ public:
+ typedef void* (TestFieldPtr::*Field);
+ Field _field;
+ TestFieldPtr();
+ void method(void*);
+ };";
+ $SOURCE1 .= "
+ TestFieldPtr::TestFieldPtr(){ }
+ void TestFieldPtr::method(void*) { }";
+
+ $HEADER2 .= "
+ class TestFieldPtr {
+ public:
+ typedef int (TestFieldPtr::*Field);
+ Field _field;
+ TestFieldPtr();
+ void method(void*);
+ };";
+ $SOURCE2 .= "
+ TestFieldPtr::TestFieldPtr(){ }
+ void TestFieldPtr::method(void*) { }";
+
+ # Removed_Symbol (Template Specializations)
+ $HEADER1 .= "
+ template <unsigned int _TP, typename AAA>
+ class Template {
+ public:
+ char const *field;
+ };
+ template <unsigned int _TP, typename AAA>
+ class TestRemovedTemplate {
+ public:
+ char const *field;
+ void method(int);
+ };
+ template <>
+ class TestRemovedTemplate<7, char> {
+ public:
+ char const *field;
+ void method(int);
+ };";
+ $SOURCE1 .= "
+ void TestRemovedTemplate<7, char>::method(int){ }";
+
+ # Removed_Symbol (Template Specializations)
+ $HEADER1 .= "
+ template <typename TName>
+ int removedTemplateSpec(TName);
+
+ template <> int removedTemplateSpec<char>(char);";
+ $SOURCE1 .= "
+ template <> int removedTemplateSpec<char>(char){return 0;}";
+
+ # Global_Data_Value (int)
+ $HEADER1 .= "
+ $EXTERN $DECL_SPEC const int globalDataValue = 10;";
+
+ $HEADER2 .= "
+ $EXTERN $DECL_SPEC const int globalDataValue = 15;";
+
+ # Global_Data_Became_Non_Const (int)
+ $HEADER1 .= "
+ $EXTERN $DECL_SPEC const int globalDataBecameNonConst = 10;";
+
+ $HEADER2 .= "
+ extern $DECL_SPEC int globalDataBecameNonConst;";
+ $SOURCE2 .= "
+ int globalDataBecameNonConst = 15;";
+
+ # Global_Data_Became_Const (safe)
+ $HEADER1 .= "
+ extern $DECL_SPEC int globalDataBecameConst;";
+ $SOURCE1 .= "
+ int globalDataBecameConst = 10;";
+
+ $HEADER2 .= "
+ $EXTERN $DECL_SPEC const int globalDataBecameConst=15;";
+
+ # Removed_Field (Ref)
+ $HEADER1 .= "
+ struct TestRefChange {
+ int a, b, c;
+ };
+ $DECL_SPEC int paramRefChange(const TestRefChange & p1, int p2);";
+ $SOURCE1 .= "
+ int paramRefChange(const TestRefChange & p1, int p2) { return p2; }";
+
+ $HEADER2 .= "
+ struct TestRefChange {
+ int a, b;
+ };
+ $DECL_SPEC int paramRefChange(const TestRefChange & p1, int p2);";
+ $SOURCE2 .= "
+ int paramRefChange(const TestRefChange & p1, int p2) { return p2; }";
+
+ # Removed_Parameter
+ $HEADER1 .= "
+ $DECL_SPEC int removedParameter(int param, int removed_param);";
+ $SOURCE1 .= "
+ int removedParameter(int param, int removed_param) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int removedParameter(int param);";
+ $SOURCE2 .= "
+ int removedParameter(int param) { return 0; }";
+
+ # Added_Parameter
+ $HEADER1 .= "
+ $DECL_SPEC int addedParameter(int param);";
+ $SOURCE1 .= "
+ int addedParameter(int param) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int addedParameter(int param, int added_param);";
+ $SOURCE2 .= "
+ int addedParameter(int param, int added_param) { return 0; }";
+
+ # Added
+ $HEADER2 .= "
+ typedef int (*FUNCPTR_TYPE)(int a, int b);
+ $DECL_SPEC int addedFunc(FUNCPTR_TYPE*const** f);";
+ $SOURCE2 .= "
+ int addedFunc(FUNCPTR_TYPE*const** f) { return 0; }";
+
+ # Added_Virtual_Method
+ $HEADER1 .= "
+ class $DECL_SPEC AddedVirtualMethod {
+ public:
+ virtual int method(int param);
+ };";
+ $SOURCE1 .= "
+ int AddedVirtualMethod::method(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC AddedVirtualMethod {
+ public:
+ virtual int addedMethod(int param);
+ virtual int method(int param);
+ };";
+ $SOURCE2 .= "
+ int AddedVirtualMethod::addedMethod(int param) {
+ return param;
+ }
+ int AddedVirtualMethod::method(int param) { return param; }";
+
+ # Added_Virtual_Method (added "virtual" attribute)
+ $HEADER1 .= "
+ class $DECL_SPEC BecameVirtualMethod {
+ public:
+ int becameVirtual(int param);
+ virtual int method(int param);
+ };";
+ $SOURCE1 .= "
+ int BecameVirtualMethod::becameVirtual(int param) { return param; }
+ int BecameVirtualMethod::method(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC BecameVirtualMethod {
+ public:
+ virtual int becameVirtual(int param);
+ virtual int method(int param);
+ };";
+ $SOURCE2 .= "
+ int BecameVirtualMethod::becameVirtual(int param) { return param; }
+ int BecameVirtualMethod::method(int param) { return param; }";
+
+ # Added_Pure_Virtual_Method
+ $HEADER1 .= "
+ class $DECL_SPEC AddedPureVirtualMethod {
+ public:
+ virtual int method(int param);
+ int otherMethod(int param);
+ };";
+ $SOURCE1 .= "
+ int AddedPureVirtualMethod::method(int param) { return param; }
+ int AddedPureVirtualMethod::otherMethod(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC AddedPureVirtualMethod {
+ public:
+ virtual int addedMethod(int param)=0;
+ virtual int method(int param);
+ int otherMethod(int param);
+ };";
+ $SOURCE2 .= "
+ int AddedPureVirtualMethod::method(int param) { return param; }
+ int AddedPureVirtualMethod::otherMethod(int param) { return param; }";
+
+ # Added_Virtual_Method_At_End (Safe)
+ $HEADER1 .= "
+ class $DECL_SPEC AddedVirtualMethodAtEnd {
+ public:
+ AddedVirtualMethodAtEnd();
+ int method1(int param);
+ virtual int method2(int param);
+ };";
+ $SOURCE1 .= "
+ AddedVirtualMethodAtEnd::AddedVirtualMethodAtEnd() { }
+ int AddedVirtualMethodAtEnd::method1(int param) { return param; }
+ int AddedVirtualMethodAtEnd::method2(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC AddedVirtualMethodAtEnd {
+ public:
+ AddedVirtualMethodAtEnd();
+ int method1(int param);
+ virtual int method2(int param);
+ virtual int addedMethod(int param);
+ };";
+ $SOURCE2 .= "
+ AddedVirtualMethodAtEnd::AddedVirtualMethodAtEnd() { }
+ int AddedVirtualMethodAtEnd::method1(int param) { return param; }
+ int AddedVirtualMethodAtEnd::method2(int param) { return param; }
+ int AddedVirtualMethodAtEnd::addedMethod(int param) { return param; }";
+
+ # Added_Virtual_Method_At_End (With Default Constructor)
+ $HEADER1 .= "
+ class $DECL_SPEC AddedVirtualMethodAtEnd_DefaultConstructor {
+ public:
+ int method1(int param);
+ virtual int method2(int param);
+ };";
+ $SOURCE1 .= "
+ int AddedVirtualMethodAtEnd_DefaultConstructor::method1(int param) { return param; }
+ int AddedVirtualMethodAtEnd_DefaultConstructor::method2(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC AddedVirtualMethodAtEnd_DefaultConstructor {
+ public:
+ int method1(int param);
+ virtual int method2(int param);
+ virtual int addedMethod(int param);
+ };";
+ $SOURCE2 .= "
+ int AddedVirtualMethodAtEnd_DefaultConstructor::method1(int param) { return param; }
+ int AddedVirtualMethodAtEnd_DefaultConstructor::method2(int param) { return param; }
+ int AddedVirtualMethodAtEnd_DefaultConstructor::addedMethod(int param) { return param; }";
+
+ # Added_First_Virtual_Method
+ $HEADER1 .= "
+ class $DECL_SPEC AddedFirstVirtualMethod {
+ public:
+ int method(int param);
+ };";
+ $SOURCE1 .= "
+ int AddedFirstVirtualMethod::method(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC AddedFirstVirtualMethod {
+ public:
+ int method(int param);
+ virtual int addedMethod(int param);
+ };";
+ $SOURCE2 .= "
+ int AddedFirstVirtualMethod::method(int param) { return param; }
+ int AddedFirstVirtualMethod::addedMethod(int param) { return param; }";
+
+ # Removed_Virtual_Method
+ $HEADER1 .= "
+ class $DECL_SPEC RemovedVirtualFunction {
+ public:
+ virtual int removedMethod(int param);
+ virtual int vMethod(int param);
+ };";
+ $SOURCE1 .= "
+ int RemovedVirtualFunction::removedMethod(int param) { return param; }
+ int RemovedVirtualFunction::vMethod(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC RemovedVirtualFunction {
+ public:
+ int removedMethod(int param);
+ virtual int vMethod(int param);
+ };";
+ $SOURCE2 .= "
+ int RemovedVirtualFunction::removedMethod(int param) { return param; }
+ int RemovedVirtualFunction::vMethod(int param) { return param; }";
+
+ # Removed_Virtual_Method (Pure, From the End)
+ $HEADER1 .= "
+ class $DECL_SPEC RemovedPureVirtualMethodFromEnd {
+ public:
+ virtual int method(int param);
+ virtual int removedMethod(int param)=0;
+ };";
+ $SOURCE1 .= "
+ int RemovedPureVirtualMethodFromEnd::method(int param) { return param; }
+ int RemovedPureVirtualMethodFromEnd::removedMethod(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC RemovedPureVirtualMethodFromEnd
+ {
+ public:
+ virtual int method(int param);
+ int removedMethod(int param);
+ };";
+ $SOURCE2 .= "
+ int RemovedPureVirtualMethodFromEnd::method(int param) { return param; }
+ int RemovedPureVirtualMethodFromEnd::removedMethod(int param) { return param; }";
+
+ # Removed_Symbol (Pure with Implementation)
+ $HEADER1 .= "
+ class $DECL_SPEC RemovedPureSymbol {
+ public:
+ virtual int method(int param);
+ virtual int removedMethod(int param)=0;
+ };";
+ $SOURCE1 .= "
+ int RemovedPureSymbol::method(int param) { return param; }
+ int RemovedPureSymbol::removedMethod(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC RemovedPureSymbol
+ {
+ public:
+ virtual int method(int param);
+ };";
+ $SOURCE2 .= "
+ int RemovedPureSymbol::method(int param) { return param; }";
+
+ # Removed_Virtual_Method (From the End)
+ $HEADER1 .= "
+ class $DECL_SPEC RemovedVirtualMethodFromEnd {
+ public:
+ virtual int method(int param);
+ virtual int removedMethod(int param);
+ };";
+ $SOURCE1 .= "
+ int RemovedVirtualMethodFromEnd::method(int param) { return param; }
+ int RemovedVirtualMethodFromEnd::removedMethod(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC RemovedVirtualMethodFromEnd
+ {
+ public:
+ virtual int method(int param);
+ int removedMethod(int param);
+ };";
+ $SOURCE2 .= "
+ int RemovedVirtualMethodFromEnd::method(int param) { return param; }
+ int RemovedVirtualMethodFromEnd::removedMethod(int param) { return param; }";
+
+ # Removed_Last_Virtual_Method
+ $HEADER1 .= "
+ class $DECL_SPEC RemovedLastVirtualMethod
+ {
+ public:
+ int method(int param);
+ virtual int removedMethod(int param);
+ };";
+ $SOURCE1 .= "
+ int RemovedLastVirtualMethod::method(int param) { return param; }";
+ $SOURCE1 .= "
+ int RemovedLastVirtualMethod::removedMethod(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC RemovedLastVirtualMethod
+ {
+ public:
+ int method(int param);
+ int removedMethod(int param);
+ };";
+ $SOURCE2 .= "
+ int RemovedLastVirtualMethod::method(int param) { return param; }";
+ $SOURCE2 .= "
+ int RemovedLastVirtualMethod::removedMethod(int param) { return param; }";
+
+ # Virtual_Table_Size
+ $HEADER1 .= "
+ class $DECL_SPEC VirtualTableSize
+ {
+ public:
+ virtual int method1(int param);
+ virtual int method2(int param);
+ };
+ class $DECL_SPEC VirtualTableSize_SubClass: public VirtualTableSize
+ {
+ public:
+ virtual int method3(int param);
+ virtual int method4(int param);
+ };";
+ $SOURCE1 .= "
+ int VirtualTableSize::method1(int param) { return param; }
+ int VirtualTableSize::method2(int param) { return param; }
+ int VirtualTableSize_SubClass::method3(int param) { return param; }
+ int VirtualTableSize_SubClass::method4(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC VirtualTableSize
+ {
+ public:
+ virtual int method1(int param);
+ virtual int method2(int param);
+ virtual int addedMethod(int param);
+ };
+ class $DECL_SPEC VirtualTableSize_SubClass: public VirtualTableSize
+ {
+ public:
+ virtual int method3(int param);
+ virtual int method4(int param);
+ };";
+ $SOURCE2 .= "
+ int VirtualTableSize::method1(int param) { return param; }
+ int VirtualTableSize::method2(int param) { return param; }
+ int VirtualTableSize::addedMethod(int param) { return param; }
+ int VirtualTableSize_SubClass::method3(int param) { return param; }
+ int VirtualTableSize_SubClass::method4(int param) { return param; }";
+
+ # Virtual_Method_Position
+ $HEADER1 .= "
+ class $DECL_SPEC VirtualMethodPosition
+ {
+ public:
+ virtual int method1(int param);
+ virtual int method2(int param);
+ };";
+ $SOURCE1 .= "
+ int VirtualMethodPosition::method1(int param) { return param; }";
+ $SOURCE1 .= "
+ int VirtualMethodPosition::method2(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC VirtualMethodPosition
+ {
+ public:
+ virtual int method2(int param);
+ virtual int method1(int param);
+ };";
+ $SOURCE2 .= "
+ int VirtualMethodPosition::method1(int param) { return param; }";
+ $SOURCE2 .= "
+ int VirtualMethodPosition::method2(int param) { return param; }";
+
+ # Pure_Virtual_Method_Position
+ $HEADER1 .= "
+ class $DECL_SPEC PureVirtualFunctionPosition {
+ public:
+ virtual int method1(int param)=0;
+ virtual int method2(int param)=0;
+ int method3(int param);
+ };";
+ $SOURCE1 .= "
+ int PureVirtualFunctionPosition::method3(int param) { return method1(7)+method2(7); }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC PureVirtualFunctionPosition {
+ public:
+ virtual int method2(int param)=0;
+ virtual int method1(int param)=0;
+ int method3(int param);
+ };";
+ $SOURCE2 .= "
+ int PureVirtualFunctionPosition::method3(int param) { return method1(7)+method2(7); }";
+
+ # Virtual_Method_Position
+ $HEADER1 .= "
+ class $DECL_SPEC VirtualFunctionPosition {
+ public:
+ virtual int method1(int param);
+ virtual int method2(int param);
+ };";
+ $SOURCE1 .= "
+ int VirtualFunctionPosition::method1(int param) { return 1; }
+ int VirtualFunctionPosition::method2(int param) { return 2; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC VirtualFunctionPosition {
+ public:
+ virtual int method2(int param);
+ virtual int method1(int param);
+ };";
+ $SOURCE2 .= "
+ int VirtualFunctionPosition::method1(int param) { return 1; }
+ int VirtualFunctionPosition::method2(int param) { return 2; }";
+
+ # Virtual_Method_Position (safe)
+ $HEADER1 .= "
+ class $DECL_SPEC VirtualFunctionPositionSafe_Base {
+ public:
+ virtual int method1(int param);
+ virtual int method2(int param);
+ };
+ class $DECL_SPEC VirtualFunctionPositionSafe: public VirtualFunctionPositionSafe_Base {
+ public:
+ virtual int method1(int param);
+ virtual int method2(int param);
+ };";
+ $SOURCE1 .= "
+ int VirtualFunctionPositionSafe_Base::method1(int param) { return param; }
+ int VirtualFunctionPositionSafe_Base::method2(int param) { return param; }
+ int VirtualFunctionPositionSafe::method1(int param) { return param; }
+ int VirtualFunctionPositionSafe::method2(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC VirtualFunctionPositionSafe_Base {
+ public:
+ virtual int method1(int param);
+ virtual int method2(int param);
+ };
+ class $DECL_SPEC VirtualFunctionPositionSafe: public VirtualFunctionPositionSafe_Base {
+ public:
+ virtual int method2(int param);
+ virtual int method1(int param);
+ };";
+ $SOURCE2 .= "
+ int VirtualFunctionPositionSafe_Base::method1(int param) { return param; }
+ int VirtualFunctionPositionSafe_Base::method2(int param) { return param; }
+ int VirtualFunctionPositionSafe::method1(int param) { return param; }
+ int VirtualFunctionPositionSafe::method2(int param) { return param; }";
+
+ # Overridden_Virtual_Method
+ $HEADER1 .= "
+ class $DECL_SPEC OverriddenVirtualMethod_Base {
+ public:
+ virtual int method1(int param);
+ virtual int method2(int param);
+ };
+ class $DECL_SPEC OverriddenVirtualMethod: public OverriddenVirtualMethod_Base {
+ public:
+ OverriddenVirtualMethod();
+ virtual int method3(int param);
+ };";
+ $SOURCE1 .= "
+ int OverriddenVirtualMethod_Base::method1(int param) { return param; }
+ int OverriddenVirtualMethod_Base::method2(int param) { return param; }
+ OverriddenVirtualMethod::OverriddenVirtualMethod() {}
+ int OverriddenVirtualMethod::method3(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC OverriddenVirtualMethod_Base {
+ public:
+ virtual int method1(int param);
+ virtual int method2(int param);
+ };
+ class $DECL_SPEC OverriddenVirtualMethod:public OverriddenVirtualMethod_Base {
+ OverriddenVirtualMethod();
+ virtual int method2(int param);
+ virtual int method3(int param);
+ };";
+ $SOURCE2 .= "
+ int OverriddenVirtualMethod_Base::method1(int param) { return param; }
+ int OverriddenVirtualMethod_Base::method2(int param) { return param; }
+ OverriddenVirtualMethod::OverriddenVirtualMethod() {}
+ int OverriddenVirtualMethod::method2(int param) { return param; }
+ int OverriddenVirtualMethod::method3(int param) { return param; }";
+
+ # Overridden_Virtual_Method_B (+ removed)
+ $HEADER1 .= "
+
+ class $DECL_SPEC OverriddenVirtualMethodB: public OverriddenVirtualMethod_Base {
+ public:
+ OverriddenVirtualMethodB();
+ virtual int method2(int param);
+ virtual int method3(int param);
+ };";
+ $SOURCE1 .= "
+ OverriddenVirtualMethodB::OverriddenVirtualMethodB() {}
+ int OverriddenVirtualMethodB::method2(int param) { return param; }
+ int OverriddenVirtualMethodB::method3(int param) { return param; }";
+
+ $HEADER2 .= "
+
+ class $DECL_SPEC OverriddenVirtualMethodB:public OverriddenVirtualMethod_Base {
+ public:
+ OverriddenVirtualMethodB();
+ virtual int method3(int param);
+ };";
+ $SOURCE2 .= "
+ OverriddenVirtualMethodB::OverriddenVirtualMethodB() {}
+ int OverriddenVirtualMethodB::method3(int param) { return param; }";
+
+ # Size
+ $HEADER1 .= "
+ struct $DECL_SPEC TypeSize
+ {
+ public:
+ TypeSize method(TypeSize param);
+ int i[5];
+ long j;
+ double k;
+ TypeSize* p;
+ };";
+ $SOURCE1 .= "
+ TypeSize TypeSize::method(TypeSize param) { return param; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC TypeSize
+ {
+ public:
+ TypeSize method(TypeSize param);
+ int i[15];
+ long j;
+ double k;
+ TypeSize* p;
+ int added_member;
+ };";
+ $SOURCE2 .= "
+ TypeSize TypeSize::method(TypeSize param) { return param; }";
+
+ # Size_Of_Allocable_Class_Increased
+ $HEADER1 .= "
+ class $DECL_SPEC AllocableClassSize
+ {
+ public:
+ AllocableClassSize();
+ int method();
+ double p[5];
+ };";
+ $SOURCE1 .= "
+ AllocableClassSize::AllocableClassSize() { }";
+ $SOURCE1 .= "
+ int AllocableClassSize::method() { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC AllocableClassSize
+ {
+ public:
+ AllocableClassSize();
+ int method();
+ double p[15];
+ };";
+ $SOURCE2 .= "
+ AllocableClassSize::AllocableClassSize() { }";
+ $SOURCE2 .= "
+ int AllocableClassSize::method() { return 0; }";
+
+ # Size_Of_Allocable_Class_Decreased (decreased size, has derived class, has public members)
+ $HEADER1 .= "
+ class $DECL_SPEC DecreasedClassSize
+ {
+ public:
+ DecreasedClassSize();
+ int method();
+ double p[15];
+ };";
+ $SOURCE1 .= "
+ DecreasedClassSize::DecreasedClassSize() { }";
+ $SOURCE1 .= "
+ int DecreasedClassSize::method() { return 0; }";
+ $HEADER1 .= "
+ class $DECL_SPEC DecreasedClassSize_SubClass: public DecreasedClassSize
+ {
+ public:
+ DecreasedClassSize_SubClass();
+ int method();
+ int f;
+ };";
+ $SOURCE1 .= "
+ DecreasedClassSize_SubClass::DecreasedClassSize_SubClass() { f=7; }";
+ $SOURCE1 .= "
+ int DecreasedClassSize_SubClass::method() { return f; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC DecreasedClassSize
+ {
+ public:
+ DecreasedClassSize();
+ int method();
+ double p[5];
+ };";
+ $SOURCE2 .= "
+ DecreasedClassSize::DecreasedClassSize() { }";
+ $SOURCE2 .= "
+ int DecreasedClassSize::method() { return 0; }";
+ $HEADER2 .= "
+ class $DECL_SPEC DecreasedClassSize_SubClass: public DecreasedClassSize
+ {
+ public:
+ DecreasedClassSize_SubClass();
+ int method();
+ int f;
+ };";
+ $SOURCE2 .= "
+ DecreasedClassSize_SubClass::DecreasedClassSize_SubClass() { f=7; }";
+ $SOURCE2 .= "
+ int DecreasedClassSize_SubClass::method() { return f; }";
+
+ # Size_Of_Copying_Class
+ $HEADER1 .= "
+ class $DECL_SPEC CopyingClassSize
+ {
+ public:
+ int method();
+ int p[5];
+ };";
+ $SOURCE1 .= "
+ int CopyingClassSize::method() { return p[4]; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC CopyingClassSize
+ {
+ public:
+ int method();
+ int p[15];
+ };";
+ $SOURCE2 .= "
+ int CopyingClassSize::method() { return p[10]; }";
+
+ # Base_Class_Became_Virtually_Inherited
+ $HEADER1 .= "
+ class $DECL_SPEC BecameVirtualBase
+ {
+ public:
+ BecameVirtualBase();
+ int method();
+ double p[5];
+ };";
+ $SOURCE1 .= "
+ BecameVirtualBase::BecameVirtualBase() { }";
+ $SOURCE1 .= "
+ int BecameVirtualBase::method() { return 0; }";
+ $HEADER1 .= "
+ class $DECL_SPEC AddedVirtualBase1:public BecameVirtualBase
+ {
+ public:
+ AddedVirtualBase1();
+ int method();
+ };";
+ $SOURCE1 .= "
+ AddedVirtualBase1::AddedVirtualBase1() { }";
+ $SOURCE1 .= "
+ int AddedVirtualBase1::method() { return 0; }";
+ $HEADER1 .= "
+ class $DECL_SPEC AddedVirtualBase2: public BecameVirtualBase
+ {
+ public:
+ AddedVirtualBase2();
+ int method();
+ };";
+ $SOURCE1 .= "
+ AddedVirtualBase2::AddedVirtualBase2() { }";
+ $SOURCE1 .= "
+ int AddedVirtualBase2::method() { return 0; }";
+ $HEADER1 .= "
+ class $DECL_SPEC BaseClassBecameVirtuallyInherited:public AddedVirtualBase1, public AddedVirtualBase2
+ {
+ public:
+ BaseClassBecameVirtuallyInherited();
+ };";
+ $SOURCE1 .= "
+ BaseClassBecameVirtuallyInherited::BaseClassBecameVirtuallyInherited() { }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC BecameVirtualBase
+ {
+ public:
+ BecameVirtualBase();
+ int method();
+ double p[5];
+ };";
+ $SOURCE2 .= "
+ BecameVirtualBase::BecameVirtualBase() { }";
+ $SOURCE2 .= "
+ int BecameVirtualBase::method() { return 0; }";
+ $HEADER2 .= "
+ class $DECL_SPEC AddedVirtualBase1:public virtual BecameVirtualBase
+ {
+ public:
+ AddedVirtualBase1();
+ int method();
+ };";
+ $SOURCE2 .= "
+ AddedVirtualBase1::AddedVirtualBase1() { }";
+ $SOURCE2 .= "
+ int AddedVirtualBase1::method() { return 0; }";
+ $HEADER2 .= "
+ class $DECL_SPEC AddedVirtualBase2: public virtual BecameVirtualBase
+ {
+ public:
+ AddedVirtualBase2();
+ int method();
+ };";
+ $SOURCE2 .= "
+ AddedVirtualBase2::AddedVirtualBase2() { }";
+ $SOURCE2 .= "
+ int AddedVirtualBase2::method() { return 0; }";
+ $HEADER2 .= "
+ class $DECL_SPEC BaseClassBecameVirtuallyInherited:public AddedVirtualBase1, public AddedVirtualBase2
+ {
+ public:
+ BaseClassBecameVirtuallyInherited();
+ };";
+ $SOURCE2 .= "
+ BaseClassBecameVirtuallyInherited::BaseClassBecameVirtuallyInherited() { }";
+
+ # Added_Base_Class, Removed_Base_Class
+ $HEADER1 .= "
+ class $DECL_SPEC BaseClass
+ {
+ public:
+ BaseClass();
+ int method();
+ double p[5];
+ };
+ class $DECL_SPEC RemovedBaseClass
+ {
+ public:
+ RemovedBaseClass();
+ int method();
+ };
+ class $DECL_SPEC ChangedBaseClass:public BaseClass, public RemovedBaseClass
+ {
+ public:
+ ChangedBaseClass();
+ };";
+ $SOURCE1 .= "
+ BaseClass::BaseClass() { }
+ int BaseClass::method() { return 0; }
+ RemovedBaseClass::RemovedBaseClass() { }
+ int RemovedBaseClass::method() { return 0; }
+ ChangedBaseClass::ChangedBaseClass() { }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC BaseClass
+ {
+ public:
+ BaseClass();
+ int method();
+ double p[5];
+ };
+ class $DECL_SPEC AddedBaseClass
+ {
+ public:
+ AddedBaseClass();
+ int method();
+ };
+ class $DECL_SPEC ChangedBaseClass:public BaseClass, public AddedBaseClass
+ {
+ public:
+ ChangedBaseClass();
+ };";
+ $SOURCE2 .= "
+ BaseClass::BaseClass() { }
+ int BaseClass::method() { return 0; }
+ AddedBaseClass::AddedBaseClass() { }
+ int AddedBaseClass::method() { return 0; }
+ ChangedBaseClass::ChangedBaseClass() { }";
+
+ # Added_Base_Class_And_Shift, Removed_Base_Class_And_Shift
+ $HEADER1 .= "
+ struct $DECL_SPEC BaseClass2
+ {
+ BaseClass2();
+ int method();
+ double p[15];
+ };
+ class $DECL_SPEC ChangedBaseClassAndSize:public BaseClass
+ {
+ public:
+ ChangedBaseClassAndSize();
+ };";
+ $SOURCE1 .= "
+ BaseClass2::BaseClass2() { }
+ int BaseClass2::method() { return 0; }
+ ChangedBaseClassAndSize::ChangedBaseClassAndSize() { }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC BaseClass2
+ {
+ BaseClass2();
+ int method();
+ double p[15];
+ };
+ class $DECL_SPEC ChangedBaseClassAndSize:public BaseClass2
+ {
+ public:
+ ChangedBaseClassAndSize();
+ };";
+ $SOURCE2 .= "
+ BaseClass2::BaseClass2() { }
+ int BaseClass2::method() { return 0; }
+ ChangedBaseClassAndSize::ChangedBaseClassAndSize() { }";
+
+ # Added_Field_And_Size
+ $HEADER1 .= "
+ struct $DECL_SPEC AddedFieldAndSize
+ {
+ int method(AddedFieldAndSize param);
+ double i, j, k;
+ AddedFieldAndSize* p;
+ };";
+ $SOURCE1 .= "
+ int AddedFieldAndSize::method(AddedFieldAndSize param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC AddedFieldAndSize
+ {
+ int method(AddedFieldAndSize param);
+ double i, j, k;
+ AddedFieldAndSize* p;
+ int added_member1;
+ long long added_member2;
+ };";
+ $SOURCE2 .= "
+ int AddedFieldAndSize::method(AddedFieldAndSize param) { return 0; }";
+
+ # Added_Field
+ $HEADER1 .= "
+ class $DECL_SPEC ObjectAddedMember
+ {
+ public:
+ int method(int param);
+ double i, j, k;
+ AddedFieldAndSize* p;
+ };";
+ $SOURCE1 .= "
+ int ObjectAddedMember::method(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC ObjectAddedMember
+ {
+ public:
+ int method(int param);
+ double i, j, k;
+ AddedFieldAndSize* p;
+ int added_member1;
+ long long added_member2;
+ };";
+ $SOURCE2 .= "
+ int ObjectAddedMember::method(int param) { return param; }";
+
+ # Added_Field (safe)
+ $HEADER1 .= "
+ struct $DECL_SPEC AddedBitfield
+ {
+ int method(AddedBitfield param);
+ double i, j, k;
+ int b1 : 32;
+ int b2 : 31;
+ AddedBitfield* p;
+ };";
+ $SOURCE1 .= "
+ int AddedBitfield::method(AddedBitfield param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC AddedBitfield
+ {
+ int method(AddedBitfield param);
+ double i, j, k;
+ int b1 : 32;
+ int b2 : 31;
+ int added_bitfield : 1;
+ int added_bitfield2 : 1;
+ AddedBitfield* p;
+ };";
+ $SOURCE2 .= "
+ int AddedBitfield::method(AddedBitfield param) { return 0; }";
+
+ # Bit_Field_Size
+ $HEADER1 .= "
+ struct $DECL_SPEC BitfieldSize
+ {
+ int method(BitfieldSize param);
+ short changed_bitfield : 1;
+ };";
+ $SOURCE1 .= "
+ int BitfieldSize::method(BitfieldSize param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC BitfieldSize
+ {
+ int method(BitfieldSize param);
+ short changed_bitfield : 7;
+ };";
+ $SOURCE2 .= "
+ int BitfieldSize::method(BitfieldSize param) { return 0; }";
+
+ # Removed_Field
+ $HEADER1 .= "
+ struct $DECL_SPEC RemovedBitfield
+ {
+ int method(RemovedBitfield param);
+ double i, j, k;
+ int b1 : 32;
+ int b2 : 31;
+ int removed_bitfield : 1;
+ RemovedBitfield* p;
+ };";
+ $SOURCE1 .= "
+ int RemovedBitfield::method(RemovedBitfield param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC RemovedBitfield
+ {
+ int method(RemovedBitfield param);
+ double i, j, k;
+ int b1 : 32;
+ int b2 : 31;
+ RemovedBitfield* p;
+ };";
+ $SOURCE2 .= "
+ int RemovedBitfield::method(RemovedBitfield param) { return 0; }";
+
+ # Removed_Middle_Field
+ $HEADER1 .= "
+ struct $DECL_SPEC RemovedMiddleBitfield
+ {
+ int method(RemovedMiddleBitfield param);
+ double i, j, k;
+ int b1 : 32;
+ int removed_middle_bitfield : 1;
+ int b2 : 31;
+ RemovedMiddleBitfield* p;
+ };";
+ $SOURCE1 .= "
+ int RemovedMiddleBitfield::method(RemovedMiddleBitfield param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC RemovedMiddleBitfield
+ {
+ int method(RemovedMiddleBitfield param);
+ double i, j, k;
+ int b1 : 32;
+ int b2 : 31;
+ RemovedMiddleBitfield* p;
+ };";
+ $SOURCE2 .= "
+ int RemovedMiddleBitfield::method(RemovedMiddleBitfield param) { return 0; }";
+
+ # Added_Middle_Field_And_Size
+ $HEADER1 .= "
+ struct $DECL_SPEC AddedMiddleFieldAndSize
+ {
+ int method(AddedMiddleFieldAndSize param);
+ int i;
+ long j;
+ double k;
+ AddedMiddleFieldAndSize* p;
+ };";
+ $SOURCE1 .= "
+ int AddedMiddleFieldAndSize::method(AddedMiddleFieldAndSize param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC AddedMiddleFieldAndSize
+ {
+ int method(AddedMiddleFieldAndSize param);
+ int i;
+ int added_middle_member;
+ long j;
+ double k;
+ AddedMiddleFieldAndSize* p;
+ };";
+ $SOURCE2 .= "
+ int AddedMiddleFieldAndSize::method(AddedMiddleFieldAndSize param) { return 0; }";
+
+ # Added_Field (padding)
+ $HEADER1 .= "
+ struct $DECL_SPEC AddedMiddlePaddedField
+ {
+ int method(int param);
+ short i;
+ long j;
+ double k;
+ };";
+ $SOURCE1 .= "
+ int AddedMiddlePaddedField::method(int param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC AddedMiddlePaddedField
+ {
+ int method(int param);
+ short i;
+ short added_padded_field;
+ long j;
+ double k;
+ };";
+ $SOURCE2 .= "
+ int AddedMiddlePaddedField::method(int param) { return 0; }";
+
+ # Added_Field (tail padding)
+ $HEADER1 .= "
+ struct $DECL_SPEC AddedTailField
+ {
+ int method(int param);
+ int i1, i2, i3, i4, i5, i6, i7;
+ short s;
+ };";
+ $SOURCE1 .= "
+ int AddedTailField::method(int param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC AddedTailField
+ {
+ int method(int param);
+ int i1, i2, i3, i4, i5, i6, i7;
+ short s;
+ short added_tail_field;
+ };";
+ $SOURCE2 .= "
+ int AddedTailField::method(int param) { return 0; }";
+
+ # Test Alignment
+ $HEADER1 .= "
+ struct $DECL_SPEC TestAlignment
+ {
+ int method(int param);
+ short s:9;
+ short j:9;
+ char c;
+ short t:9;
+ short u:9;
+ char d;
+ };";
+ $SOURCE1 .= "
+ int TestAlignment::method(int param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC TestAlignment
+ {
+ int method(int param);
+ short s:9;
+ short j:9;
+ char c;
+ short t:9;
+ short u:9;
+ char d;
+ };";
+ $SOURCE2 .= "
+ int TestAlignment::method(int param) { return 0; }";
+
+ # Renamed_Field
+ $HEADER1 .= "
+ struct $DECL_SPEC RenamedField
+ {
+ int method(RenamedField param);
+ long i;
+ long j;
+ double k;
+ RenamedField* p;
+ };";
+ $SOURCE1 .= "
+ int RenamedField::method(RenamedField param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC RenamedField
+ {
+ int method(RenamedField param);
+ long renamed_member;
+ long j;
+ double k;
+ RenamedField* p;
+ };";
+ $SOURCE2 .= "
+ int RenamedField::method(RenamedField param) { return 0; }";
+
+ # Removed_Field_And_Size
+ $HEADER1 .= "
+ struct $DECL_SPEC RemovedFieldAndSize
+ {
+ int method(RemovedFieldAndSize param);
+ double i, j, k;
+ RemovedFieldAndSize* p;
+ int removed_member1;
+ long removed_member2;
+ };";
+ $SOURCE1 .= "
+ int RemovedFieldAndSize::method(RemovedFieldAndSize param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC RemovedFieldAndSize
+ {
+ int method(RemovedFieldAndSize param);
+ double i, j, k;
+ RemovedFieldAndSize* p;
+ };";
+ $SOURCE2 .= "
+ int RemovedFieldAndSize::method(RemovedFieldAndSize param) { return 0; }";
+
+ # Field Position
+ $HEADER1 .= "
+ struct $DECL_SPEC MovedField
+ {
+ int method(int param);
+ double i;
+ int j;
+ };";
+ $SOURCE1 .= "
+ int MovedField::method(int param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC MovedField
+ {
+ int method(int param);
+ int j;
+ double i;
+ };";
+ $SOURCE2 .= "
+ int MovedField::method(int param) { return 0; }";
+
+ # Removed_Middle_Field_And_Size
+ $HEADER1 .= "
+ struct $DECL_SPEC RemovedMiddleFieldAndSize
+ {
+ int method(RemovedMiddleFieldAndSize param);
+ int i;
+ int removed_middle_member;
+ long j;
+ double k;
+ RemovedMiddleFieldAndSize* p;
+ };";
+ $SOURCE1 .= "
+ int RemovedMiddleFieldAndSize::method(RemovedMiddleFieldAndSize param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC RemovedMiddleFieldAndSize
+ {
+ int method(RemovedMiddleFieldAndSize param);
+ int i;
+ long j;
+ double k;
+ RemovedMiddleFieldAndSize* p;
+ };";
+ $SOURCE2 .= "
+ int RemovedMiddleFieldAndSize::method(RemovedMiddleFieldAndSize param) { return 0; }";
+
+ # Enum_Member_Value
+ $HEADER1 .= "
+ enum EnumMemberValue
+ {
+ MEMBER_1=1,
+ MEMBER_2=2
+ };";
+ $HEADER1 .= "
+ $DECL_SPEC int enumMemberValueChange(enum EnumMemberValue param);";
+ $SOURCE1 .= "
+ int enumMemberValueChange(enum EnumMemberValue param) { return 0; }";
+
+ $HEADER2 .= "
+ enum EnumMemberValue
+ {
+ MEMBER_1=2,
+ MEMBER_2=1
+ };";
+ $HEADER2 .= "
+ $DECL_SPEC int enumMemberValueChange(enum EnumMemberValue param);";
+ $SOURCE2 .= "
+ int enumMemberValueChange(enum EnumMemberValue param) { return 0; }";
+
+ # Enum_Member_Name
+ $HEADER1 .= "
+ enum EnumMemberRename
+ {
+ BRANCH_1=1,
+ BRANCH_2=2
+ };";
+ $HEADER1 .= "
+ $DECL_SPEC int enumMemberRename(enum EnumMemberRename param);";
+ $SOURCE1 .= "
+ int enumMemberRename(enum EnumMemberRename param) { return 0; }";
+
+ $HEADER2 .= "
+ enum EnumMemberRename
+ {
+ BRANCH_FIRST=1,
+ BRANCH_SECOND=2
+ };";
+ $HEADER2 .= "
+ $DECL_SPEC int enumMemberRename(enum EnumMemberRename param);";
+ $SOURCE2 .= "
+ int enumMemberRename(enum EnumMemberRename param) { return 0; }";
+
+ # Field_Type_And_Size
+ $HEADER1 .= "
+ struct $DECL_SPEC FieldTypeAndSize
+ {
+ int method(FieldTypeAndSize param);
+ int i;
+ long j;
+ double k;
+ FieldTypeAndSize* p;
+ };";
+ $SOURCE1 .= "
+ int FieldTypeAndSize::method(FieldTypeAndSize param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC FieldTypeAndSize
+ {
+ int method(FieldTypeAndSize param);
+ long long i;
+ long j;
+ double k;
+ FieldTypeAndSize* p;
+ };";
+ $SOURCE2 .= "
+ int FieldTypeAndSize::method(FieldTypeAndSize param) { return 0; }";
+
+ # Member_Type
+ $HEADER1 .= "
+ struct $DECL_SPEC MemberType
+ {
+ int method(MemberType param);
+ int i;
+ long j;
+ double k;
+ MemberType* p;
+ };";
+ $SOURCE1 .= "
+ int MemberType::method(MemberType param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC MemberType
+ {
+ int method(MemberType param);
+ float i;
+ long j;
+ double k;
+ MemberType* p;
+ };";
+ $SOURCE2 .= "
+ int MemberType::method(MemberType param) { return 0; }";
+
+ # Field_BaseType
+ $HEADER1 .= "
+ struct $DECL_SPEC FieldBaseType
+ {
+ int method(FieldBaseType param);
+ int *i;
+ long j;
+ double k;
+ FieldBaseType* p;
+ };";
+ $SOURCE1 .= "
+ int FieldBaseType::method(FieldBaseType param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC FieldBaseType
+ {
+ int method(FieldBaseType param);
+ long long *i;
+ long j;
+ double k;
+ FieldBaseType* p;
+ };";
+ $SOURCE2 .= "
+ int FieldBaseType::method(FieldBaseType param) { return 0; }";
+
+ # Field_PointerLevel_Increased (and size)
+ $HEADER1 .= "
+ struct $DECL_SPEC FieldPointerLevelAndSize
+ {
+ int method(FieldPointerLevelAndSize param);
+ long long i;
+ long j;
+ double k;
+ FieldPointerLevelAndSize* p;
+ };";
+ $SOURCE1 .= "
+ int FieldPointerLevelAndSize::method(FieldPointerLevelAndSize param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC FieldPointerLevelAndSize
+ {
+ int method(FieldPointerLevelAndSize param);
+ long long *i;
+ long j;
+ double k;
+ FieldPointerLevelAndSize* p;
+ };";
+ $SOURCE2 .= "
+ int FieldPointerLevelAndSize::method(FieldPointerLevelAndSize param) { return 0; }";
+
+ # Field_PointerLevel
+ $HEADER1 .= "
+ struct $DECL_SPEC FieldPointerLevel
+ {
+ int method(FieldPointerLevel param);
+ int **i;
+ long j;
+ double k;
+ FieldPointerLevel* p;
+ };";
+ $SOURCE1 .= "
+ int FieldPointerLevel::method(FieldPointerLevel param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC FieldPointerLevel
+ {
+ int method(FieldPointerLevel param);
+ int *i;
+ long j;
+ double k;
+ FieldPointerLevel* p;
+ };";
+ $SOURCE2 .= "
+ int FieldPointerLevel::method(FieldPointerLevel param) { return 0; }";
+
+ # Added_Interface (method)
+ $HEADER1 .= "
+ struct $DECL_SPEC AddedInterface
+ {
+ int method(AddedInterface param);
+ int i;
+ long j;
+ double k;
+ AddedInterface* p;
+ };";
+ $SOURCE1 .= "
+ int AddedInterface::method(AddedInterface param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC AddedInterface
+ {
+ int method(AddedInterface param);
+ int added_func(AddedInterface param);
+ int i;
+ long j;
+ double k;
+ AddedInterface* p;
+ };";
+ $SOURCE2 .= "
+ int AddedInterface::method(AddedInterface param) { return 0; }";
+ $SOURCE2 .= "
+ int AddedInterface::added_func(AddedInterface param) { return 0; }";
+
+ # Added_Interface (function)
+ $HEADER2 .= "
+ $DECL_SPEC int addedFunc2(void *** param);";
+ $SOURCE2 .= "
+ int addedFunc2(void *** param) { return 0; }";
+
+ # Added_Interface (global variable)
+ $HEADER1 .= "
+ struct $DECL_SPEC AddedVariable
+ {
+ int method(AddedVariable param);
+ int i1, i2;
+ long j;
+ double k;
+ AddedVariable* p;
+ };";
+ $SOURCE1 .= "
+ int AddedVariable::method(AddedVariable param) {
+ return i1;
+ }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC AddedVariable
+ {
+ int method(AddedVariable param);
+ static int i1;
+ static int i2;
+ long j;
+ double k;
+ AddedVariable* p;
+ };";
+ $SOURCE2 .= "
+ int AddedVariable::method(AddedVariable param) { return AddedVariable::i1; }";
+ $SOURCE2 .= "
+ int AddedVariable::i1=0;";
+ $SOURCE2 .= "
+ int AddedVariable::i2=0;";
+
+ # Removed_Interface (method)
+ $HEADER1 .= "
+ struct $DECL_SPEC RemovedInterface
+ {
+ int method(RemovedInterface param);
+ int removed_func(RemovedInterface param);
+ int i;
+ long j;
+ double k;
+ RemovedInterface* p;
+ };";
+ $SOURCE1 .= "
+ int RemovedInterface::method(RemovedInterface param) { return 0; }";
+ $SOURCE1 .= "
+ int RemovedInterface::removed_func(RemovedInterface param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC RemovedInterface
+ {
+ int method(RemovedInterface param);
+ int i;
+ long j;
+ double k;
+ RemovedInterface* p;
+ };";
+ $SOURCE2 .= "
+ int RemovedInterface::method(RemovedInterface param) { return 0; }";
+
+ # Removed_Interface (function)
+ $HEADER1 .= "
+ $DECL_SPEC int removedFunc2(void *** param);";
+ $SOURCE1 .= "
+ int removedFunc2(void *** param) { return 0; }";
+
+ # Method_Became_Static
+ $HEADER1 .= "
+ struct $DECL_SPEC MethodBecameStatic
+ {
+ MethodBecameStatic becameStatic(MethodBecameStatic param);
+ int **i;
+ long j;
+ double k;
+ MethodBecameStatic* p;
+ };";
+ $SOURCE1 .= "
+ MethodBecameStatic MethodBecameStatic::becameStatic(MethodBecameStatic param) { return param; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC MethodBecameStatic
+ {
+ static MethodBecameStatic becameStatic(MethodBecameStatic param);
+ int **i;
+ long j;
+ double k;
+ MethodBecameStatic* p;
+ };";
+ $SOURCE2 .= "
+ MethodBecameStatic MethodBecameStatic::becameStatic(MethodBecameStatic param) { return param; }";
+
+ # Method_Became_NonStatic
+ $HEADER1 .= "
+ struct $DECL_SPEC MethodBecameNonStatic
+ {
+ static MethodBecameNonStatic becameNonStatic(MethodBecameNonStatic param);
+ int **i;
+ long j;
+ double k;
+ MethodBecameNonStatic* p;
+ };";
+ $SOURCE1 .= "
+ MethodBecameNonStatic MethodBecameNonStatic::becameNonStatic(MethodBecameNonStatic param) { return param; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC MethodBecameNonStatic
+ {
+ MethodBecameNonStatic becameNonStatic(MethodBecameNonStatic param);
+ int **i;
+ long j;
+ double k;
+ MethodBecameNonStatic* p;
+ };";
+ $SOURCE2 .= "
+ MethodBecameNonStatic MethodBecameNonStatic::becameNonStatic(MethodBecameNonStatic param) { return param; }";
+
+ # Parameter_Type_And_Size
+ $HEADER1 .= "
+ $DECL_SPEC int funcParameterTypeAndSize(int param, int other_param);";
+ $SOURCE1 .= "
+ int funcParameterTypeAndSize(int param, int other_param) { return other_param; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int funcParameterTypeAndSize(long long param, int other_param);";
+ $SOURCE2 .= "
+ int funcParameterTypeAndSize(long long param, int other_param) { return other_param; }";
+
+ # Parameter_Type
+ $HEADER1 .= "
+ $DECL_SPEC int funcParameterType(int param, int other_param);";
+ $SOURCE1 .= "
+ int funcParameterType(int param, int other_param) { return other_param; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int funcParameterType(float param, int other_param);";
+ $SOURCE2 .= "
+ int funcParameterType(float param, int other_param) { return other_param; }";
+
+ # Parameter_BaseType
+ $HEADER1 .= "
+ $DECL_SPEC int funcParameterBaseType(int *param);";
+ $SOURCE1 .= "
+ int funcParameterBaseType(int *param) { return sizeof(*param); }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int funcParameterBaseType(long long *param);";
+ $SOURCE2 .= "
+ int funcParameterBaseType(long long *param) { return sizeof(*param); }";
+
+ # Parameter_PointerLevel
+ $HEADER1 .= "
+ $DECL_SPEC long long funcParameterPointerLevelAndSize(long long param);";
+ $SOURCE1 .= "
+ long long funcParameterPointerLevelAndSize(long long param) { return param; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC long long funcParameterPointerLevelAndSize(long long *param);";
+ $SOURCE2 .= "
+ long long funcParameterPointerLevelAndSize(long long *param) { return param[5]; }";
+
+ # Parameter_PointerLevel
+ $HEADER1 .= "
+ $DECL_SPEC int funcParameterPointerLevel(int *param);";
+ $SOURCE1 .= "
+ int funcParameterPointerLevel(int *param) { return param[5]; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int funcParameterPointerLevel(int **param);";
+ $SOURCE2 .= "
+ int funcParameterPointerLevel(int **param) { return param[5][5]; }";
+
+ # Return_Type_And_Size
+ $HEADER1 .= "
+ $DECL_SPEC int funcReturnTypeAndSize(int param);";
+ $SOURCE1 .= "
+ int funcReturnTypeAndSize(int param) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC long long funcReturnTypeAndSize(int param);";
+ $SOURCE2 .= "
+ long long funcReturnTypeAndSize(int param) { return 0; }";
+
+ # Return_Type
+ $HEADER1 .= "
+ $DECL_SPEC int funcReturnType(int param);";
+ $SOURCE1 .= "
+ int funcReturnType(int param) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC float funcReturnType(int param);";
+ $SOURCE2 .= "
+ float funcReturnType(int param) { return 0.7; }";
+
+ # Return_Type_Became_Void ("int" to "void")
+ $HEADER1 .= "
+ $DECL_SPEC int funcReturnTypeBecameVoid(int param);";
+ $SOURCE1 .= "
+ int funcReturnTypeBecameVoid(int param) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC void funcReturnTypeBecameVoid(int param);";
+ $SOURCE2 .= "
+ void funcReturnTypeBecameVoid(int param) { return; }";
+
+ # Return_BaseType
+ $HEADER1 .= "
+ $DECL_SPEC int* funcReturnBaseType(int param);";
+ $SOURCE1 .= "
+ int* funcReturnBaseType(int param) {
+ int *x = new int[10];
+ return x;
+ }";
+
+ $HEADER2 .= "
+ $DECL_SPEC long long* funcReturnBaseType(int param);";
+ $SOURCE2 .= "
+ long long* funcReturnBaseType(int param) {
+ long long *x = new long long[10];
+ return x;
+ }";
+
+ # Return_PointerLevel
+ $HEADER1 .= "
+ $DECL_SPEC long long funcReturnPointerLevelAndSize(int param);";
+ $SOURCE1 .= "
+ long long funcReturnPointerLevelAndSize(int param) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC long long* funcReturnPointerLevelAndSize(int param);";
+ $SOURCE2 .= "
+ long long* funcReturnPointerLevelAndSize(int param) { return new long long[10]; }";
+
+ # Return_PointerLevel
+ $HEADER1 .= "
+ $DECL_SPEC int* funcReturnPointerLevel(int param);";
+ $SOURCE1 .= "
+ int* funcReturnPointerLevel(int param) { return new int[10]; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int** funcReturnPointerLevel(int param);";
+ $SOURCE2 .= "
+ int** funcReturnPointerLevel(int param) { return new int*[10]; }";
+
+ # Size (anon type)
+ $HEADER1 .= "
+ typedef struct {
+ int i;
+ long j;
+ double k;
+ } AnonTypedef;
+ $DECL_SPEC int funcAnonTypedef(AnonTypedef param);";
+ $SOURCE1 .= "
+ int funcAnonTypedef(AnonTypedef param) { return 0; }";
+
+ $HEADER2 .= "
+ typedef struct {
+ int i;
+ long j;
+ double k;
+ union {
+ int dummy[256];
+ struct {
+ char q_skiptable[256];
+ const char *p;
+ int l;
+ } p;
+ };
+ } AnonTypedef;
+ $DECL_SPEC int funcAnonTypedef(AnonTypedef param);";
+ $SOURCE2 .= "
+ int funcAnonTypedef(AnonTypedef param) { return 0; }";
+
+ # Added_Field (safe: opaque)
+ $HEADER1 .= "
+ struct $DECL_SPEC OpaqueType
+ {
+ public:
+ OpaqueType method(OpaqueType param);
+ int i;
+ long j;
+ double k;
+ OpaqueType* p;
+ };";
+ $SOURCE1 .= "
+ OpaqueType OpaqueType::method(OpaqueType param) { return param; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC OpaqueType
+ {
+ public:
+ OpaqueType method(OpaqueType param);
+ int i;
+ long j;
+ double k;
+ OpaqueType* p;
+ int added_member;
+ };";
+ $SOURCE2 .= "
+ OpaqueType OpaqueType::method(OpaqueType param) { return param; }";
+
+ # Added_Field (safe: internal)
+ $HEADER1 .= "
+ struct $DECL_SPEC InternalType {
+ InternalType method(InternalType param);
+ int i;
+ long j;
+ double k;
+ InternalType* p;
+ };";
+ $SOURCE1 .= "
+ InternalType InternalType::method(InternalType param) { return param; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC InternalType {
+ InternalType method(InternalType param);
+ int i;
+ long j;
+ double k;
+ InternalType* p;
+ int added_member;
+ };";
+ $SOURCE2 .= "
+ InternalType InternalType::method(InternalType param) { return param; }";
+
+ # Size (unnamed struct/union fields within structs/unions)
+ $HEADER1 .= "
+ typedef struct {
+ int a;
+ struct {
+ int u1;
+ float u2;
+ };
+ int d;
+ } UnnamedTypeSize;
+ $DECL_SPEC int unnamedTypeSize(UnnamedTypeSize param);";
+ $SOURCE1 .= "
+ int unnamedTypeSize(UnnamedTypeSize param) { return 0; }";
+
+ $HEADER2 .= "
+ typedef struct {
+ int a;
+ struct {
+ long double u1;
+ float u2;
+ };
+ int d;
+ } UnnamedTypeSize;
+ $DECL_SPEC int unnamedTypeSize(UnnamedTypeSize param);";
+ $SOURCE2 .= "
+ int unnamedTypeSize(UnnamedTypeSize param) { return 0; }";
+
+ # constants
+ $HEADER1 .= "
+ #define PUBLIC_CONSTANT \"old_value\"";
+ $HEADER2 .= "
+ #define PUBLIC_CONSTANT \"new_value\"";
+
+ $HEADER1 .= "
+ #define PRIVATE_CONSTANT \"old_value\"
+ #undef PRIVATE_CONSTANT";
+ $HEADER2 .= "
+ #define PRIVATE_CONSTANT \"new_value\"
+ #undef PRIVATE_CONSTANT";
+
+ # Added_Field (union)
+ $HEADER1 .= "
+ union UnionAddedField {
+ int a;
+ struct {
+ int b;
+ float c;
+ };
+ int d;
+ };
+ $DECL_SPEC int unionAddedField(UnionAddedField param);";
+ $SOURCE1 .= "
+ int unionAddedField(UnionAddedField param) { return 0; }";
+
+ $HEADER2 .= "
+ union UnionAddedField {
+ int a;
+ struct {
+ long double x, y;
+ } new_field;
+ struct {
+ int b;
+ float c;
+ };
+ int d;
+ };
+ $DECL_SPEC int unionAddedField(UnionAddedField param);";
+ $SOURCE2 .= "
+ int unionAddedField(UnionAddedField param) { return 0; }";
+
+ # Removed_Field (union)
+ $HEADER1 .= "
+ union UnionRemovedField {
+ int a;
+ struct {
+ long double x, y;
+ } removed_field;
+ struct {
+ int b;
+ float c;
+ };
+ int d;
+ };
+ $DECL_SPEC int unionRemovedField(UnionRemovedField param);";
+ $SOURCE1 .= "
+ int unionRemovedField(UnionRemovedField param) { return 0; }";
+
+ $HEADER2 .= "
+ union UnionRemovedField {
+ int a;
+ struct {
+ int b;
+ float c;
+ };
+ int d;
+ };
+ $DECL_SPEC int unionRemovedField(UnionRemovedField param);";
+ $SOURCE2 .= "
+ int unionRemovedField(UnionRemovedField param) { return 0; }";
+
+ # Added (typedef change)
+ $HEADER1 .= "
+ typedef float TYPEDEF_TYPE;
+ $DECL_SPEC int parameterTypedefChange(TYPEDEF_TYPE param);";
+ $SOURCE1 .= "
+ int parameterTypedefChange(TYPEDEF_TYPE param) { return 1; }";
+
+ $HEADER2 .= "
+ typedef int TYPEDEF_TYPE;
+ $DECL_SPEC int parameterTypedefChange(TYPEDEF_TYPE param);";
+ $SOURCE2 .= "
+ int parameterTypedefChange(TYPEDEF_TYPE param) { return 1; }";
+
+ # Parameter_Default_Value_Changed
+ $HEADER1 .= "
+ $DECL_SPEC int parameterDefaultValueChanged(int param = 0xf00f); ";
+ $SOURCE1 .= "
+ int parameterDefaultValueChanged(int param) { return param; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int parameterDefaultValueChanged(int param = 0xf00b); ";
+ $SOURCE2 .= "
+ int parameterDefaultValueChanged(int param) { return param; }";
+
+ # Parameter_Default_Value_Changed (char const *)
+ $HEADER1 .= "
+ $DECL_SPEC int parameterDefaultStringValueChanged(char const* param = \" str 1 \"); ";
+ $SOURCE1 .= "
+ int parameterDefaultStringValueChanged(char const* param) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int parameterDefaultStringValueChanged(char const* param = \" str 2 \"); ";
+ $SOURCE2 .= "
+ int parameterDefaultStringValueChanged(char const* param) { return 0; }";
+
+ # Parameter_Default_Value_Removed
+ $HEADER1 .= "
+ $DECL_SPEC int parameterDefaultValueRemoved(int param = 0xf00f);
+ ";
+ $SOURCE1 .= "
+ int parameterDefaultValueRemoved(int param) { return param; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int parameterDefaultValueRemoved(int param);";
+ $SOURCE2 .= "
+ int parameterDefaultValueRemoved(int param) { return param; }";
+
+ # Field_Type (typedefs in member type)
+ $HEADER1 .= "
+ typedef float TYPEDEF_TYPE_2;
+ struct $DECL_SPEC FieldTypedefChange{
+ public:
+ TYPEDEF_TYPE_2 m;
+ TYPEDEF_TYPE_2 n;
+ };
+ $DECL_SPEC int fieldTypedefChange(FieldTypedefChange param);";
+ $SOURCE1 .= "
+ int fieldTypedefChange(FieldTypedefChange param) { return 1; }";
+
+ $HEADER2 .= "
+ typedef int TYPEDEF_TYPE_2;
+ struct $DECL_SPEC FieldTypedefChange{
+ public:
+ TYPEDEF_TYPE_2 m;
+ TYPEDEF_TYPE_2 n;
+ };
+ $DECL_SPEC int fieldTypedefChange(FieldTypedefChange param);";
+ $SOURCE2 .= "
+ int fieldTypedefChange(FieldTypedefChange param) { return 1; }";
+
+ # Callback (testCallback symbol should be affected
+ # instead of callback1 and callback2)
+ $HEADER1 .= "
+ class $DECL_SPEC Callback {
+ public:
+ virtual int callback1(int x, int y)=0;
+ virtual int callback2(int x, int y)=0;
+ };
+ $DECL_SPEC int testCallback(Callback* p);";
+ $SOURCE1 .= "
+ int testCallback(Callback* p) {
+ p->callback2(1, 2);
+ return 0;
+ }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC Callback {
+ public:
+ virtual int callback1(int x, int y)=0;
+ virtual int added_callback(int x, int y)=0;
+ virtual int callback2(int x, int y)=0;
+ };
+ $DECL_SPEC int testCallback(Callback* p);";
+ $SOURCE2 .= "
+ int testCallback(Callback* p) {
+ p->callback2(1, 2);
+ return 0;
+ }";
+
+ # End namespace
+ $HEADER1 .= "\n}\n";
+ $HEADER2 .= "\n}\n";
+ $SOURCE1 .= "\n}\n";
+ $SOURCE2 .= "\n}\n";
+
+ runTests("libsample_cpp", "C++", $HEADER1, $SOURCE1, $HEADER2, $SOURCE2, "TestNS::OpaqueType", "_ZN6TestNS12InternalType6methodES0_");
+}
+
+sub testC()
+{
+ printMsg("INFO", "\nverifying detectable C library changes");
+ my ($HEADER1, $SOURCE1, $HEADER2, $SOURCE2) = ();
+ my $DECL_SPEC = ($OSgroup eq "windows")?"__declspec( dllexport )":"";
+ my $EXTERN = ($OSgroup eq "windows")?"extern ":"";
+
+ # Parameter_Type (int to "int const")
+ $HEADER1 .= "
+ $DECL_SPEC void parameterBecameConstInt(int arg);";
+ $SOURCE1 .= "
+ void parameterBecameConstInt(int arg) { }";
+
+ $HEADER2 .= "
+ $DECL_SPEC void parameterBecameConstInt(const int arg);";
+ $SOURCE2 .= "
+ void parameterBecameConstInt(const int arg) { }";
+
+ # Parameter_Type ("int const" to int)
+ $HEADER1 .= "
+ $DECL_SPEC void parameterBecameNonConstInt(const int arg);";
+ $SOURCE1 .= "
+ void parameterBecameNonConstInt(const int arg) { }";
+
+ $HEADER2 .= "
+ $DECL_SPEC void parameterBecameNonConstInt(int arg);";
+ $SOURCE2 .= "
+ void parameterBecameNonConstInt(int arg) { }";
+
+ # Parameter_Became_Register
+ $HEADER1 .= "
+ $DECL_SPEC void parameterBecameRegister(int arg);";
+ $SOURCE1 .= "
+ void parameterBecameRegister(int arg) { }";
+
+ $HEADER2 .= "
+ $DECL_SPEC void parameterBecameRegister(register int arg);";
+ $SOURCE2 .= "
+ void parameterBecameRegister(register int arg) { }";
+
+ # Return_Type_Became_Const
+ $HEADER1 .= "
+ $DECL_SPEC char* returnTypeBecameConst(int param);";
+ $SOURCE1 .= "
+ char* returnTypeBecameConst(int param) { return (char*)malloc(256); }";
+
+ $HEADER2 .= "
+ $DECL_SPEC const char* returnTypeBecameConst(int param);";
+ $SOURCE2 .= "
+ const char* returnTypeBecameConst(int param) { return \"abc\"; }";
+
+ # Return_Type_Became_Const (2)
+ $HEADER1 .= "
+ $DECL_SPEC char* returnTypeBecameConst2(int param);";
+ $SOURCE1 .= "
+ char* returnTypeBecameConst2(int param) { return (char*)malloc(256); }";
+
+ $HEADER2 .= "
+ $DECL_SPEC char*const returnTypeBecameConst2(int param);";
+ $SOURCE2 .= "
+ char*const returnTypeBecameConst2(int param) { return (char*const)malloc(256); }";
+
+ # Return_Type_Became_Const (3)
+ $HEADER1 .= "
+ $DECL_SPEC char* returnTypeBecameConst3(int param);";
+ $SOURCE1 .= "
+ char* returnTypeBecameConst3(int param) { return (char*)malloc(256); }";
+
+ $HEADER2 .= "
+ $DECL_SPEC char const*const returnTypeBecameConst3(int param);";
+ $SOURCE2 .= "
+ char const*const returnTypeBecameConst3(int param) { return (char const*const)malloc(256); }";
+
+ # Added_Enum_Member
+ $HEADER1 .= "
+ enum AddedEnumMember {
+ OldMember
+ };
+ $DECL_SPEC int addedEnumMember(enum AddedEnumMember param);";
+ $SOURCE1 .= "
+ int addedEnumMember(enum AddedEnumMember param) { return 0; }";
+
+ $HEADER2 .= "
+ enum AddedEnumMember {
+ OldMember,
+ NewMember
+ };
+ $DECL_SPEC int addedEnumMember(enum AddedEnumMember param);";
+ $SOURCE2 .= "
+ int addedEnumMember(enum AddedEnumMember param) { return 0; }";
+
+ # Parameter_Type (Array)
+ $HEADER1 .= "
+ $DECL_SPEC int arrayParameterType(int param[5]);";
+ $SOURCE1 .= "
+ int arrayParameterType(int param[5]) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int arrayParameterType(int param[7]);";
+ $SOURCE2 .= "
+ int arrayParameterType(int param[7]) { return 0; }";
+
+ # Field_Type
+ $HEADER1 .= "
+ struct ArrayFieldType
+ {
+ int f;
+ int i[1];
+ };
+ $DECL_SPEC int arrayFieldType(struct ArrayFieldType param);";
+ $SOURCE1 .= "
+ int arrayFieldType(struct ArrayFieldType param) { return param.i[0]; }";
+
+ $HEADER2 .= "
+ struct ArrayFieldType
+ {
+ int f;
+ int i[];
+ };
+ $DECL_SPEC int arrayFieldType(struct ArrayFieldType param);";
+ $SOURCE2 .= "
+ int arrayFieldType(struct ArrayFieldType param) { return param.i[0]; }";
+
+ # Field_Type_And_Size (Array)
+ $HEADER1 .= "
+ struct ArrayFieldSize
+ {
+ int i[5];
+ };
+ $DECL_SPEC int arrayFieldSize(struct ArrayFieldSize param);";
+ $SOURCE1 .= "
+ int arrayFieldSize(struct ArrayFieldSize param) { return 0; }";
+
+ $HEADER2 .= "
+ struct ArrayFieldSize
+ {
+ int i[7];
+ };
+ $DECL_SPEC int arrayFieldSize(struct ArrayFieldSize param);";
+ $SOURCE2 .= "
+ int arrayFieldSize(struct ArrayFieldSize param) { return 0; }";
+
+ # Parameter_Became_NonVaList
+ $HEADER1 .= "
+ $DECL_SPEC int parameterNonVaList(int param, ...);";
+ $SOURCE1 .= "
+ int parameterNonVaList(int param, ...) { return param; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int parameterNonVaList(int param1, int param2);";
+ $SOURCE2 .= "
+ int parameterNonVaList(int param1, int param2) { return param1; }";
+
+ # Parameter_Became_VaList
+ $HEADER1 .= "
+ $DECL_SPEC int parameterVaList(int param1, int param2);";
+ $SOURCE1 .= "
+ int parameterVaList(int param1, int param2) { return param1; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int parameterVaList(int param, ...);";
+ $SOURCE2 .= "
+ int parameterVaList(int param, ...) { return param; }";
+
+ # Field_Type_And_Size
+ $HEADER1 .= "
+ struct FieldSizePadded
+ {
+ int i;
+ char changed_field;
+ // padding (3 bytes)
+ int j;
+ };
+ $DECL_SPEC int fieldSizePadded(struct FieldSizePadded param);";
+ $SOURCE1 .= "
+ int fieldSizePadded(struct FieldSizePadded param) { return 0; }";
+
+ $HEADER2 .= "
+ struct FieldSizePadded
+ {
+ int i;
+ int changed_field;
+ int j;
+ };
+ $DECL_SPEC int fieldSizePadded(struct FieldSizePadded param);";
+ $SOURCE2 .= "
+ int fieldSizePadded(struct FieldSizePadded param) { return 0; }";
+
+ # Parameter_Type_Format
+ $HEADER1 .= "
+ struct DType1
+ {
+ int i;
+ double j;
+ };
+ $DECL_SPEC int parameterTypeFormat(struct DType1 param);";
+ $SOURCE1 .= "
+ int parameterTypeFormat(struct DType1 param) { return 0; }";
+
+ $HEADER2 .= "
+ struct DType2
+ {
+ double i;
+ int j;
+ };
+ $DECL_SPEC int parameterTypeFormat(struct DType2 param);";
+ $SOURCE2 .= "
+ int parameterTypeFormat(struct DType2 param) { return 0; }";
+
+ # Parameter_Type_Format (struct to union)
+ $HEADER1 .= "
+ struct DType
+ {
+ int i;
+ double j;
+ };
+ $DECL_SPEC int parameterTypeFormat2(struct DType param);";
+ $SOURCE1 .= "
+ int parameterTypeFormat2(struct DType param) { return 0; }";
+
+ $HEADER2 .= "
+ union DType
+ {
+ int i;
+ long double j;
+ };
+ $DECL_SPEC int parameterTypeFormat2(union DType param);";
+ $SOURCE2 .= "
+ int parameterTypeFormat2(union DType param) { return 0; }";
+
+ # Global_Data_Size
+ $HEADER1 .= "
+ struct GlobalDataSize {
+ int a;
+ };
+ $EXTERN $DECL_SPEC struct GlobalDataSize globalDataSize;";
+
+ $HEADER2 .= "
+ struct GlobalDataSize {
+ int a, b;
+ };
+ $EXTERN $DECL_SPEC struct GlobalDataSize globalDataSize;";
+
+ # Global_Data_Type
+ $HEADER1 .= "
+ $EXTERN $DECL_SPEC int globalDataType;";
+
+ $HEADER2 .= "
+ $EXTERN $DECL_SPEC float globalDataType;";
+
+ # Global_Data_Type_And_Size
+ $HEADER1 .= "
+ $EXTERN $DECL_SPEC int globalDataTypeAndSize;";
+
+ $HEADER2 .= "
+ $EXTERN $DECL_SPEC short globalDataTypeAndSize;";
+
+ # Global_Data_Value (int)
+ $HEADER1 .= "
+ $EXTERN $DECL_SPEC const int globalDataValue = 10;";
+
+ $HEADER2 .= "
+ $EXTERN $DECL_SPEC const int globalDataValue = 15;";
+
+ # Global_Data_Became_Non_Const (int)
+ $HEADER1 .= "
+ $EXTERN $DECL_SPEC const int globalDataBecameNonConst = 10;";
+
+ $HEADER2 .= "
+ extern $DECL_SPEC int globalDataBecameNonConst;";
+ $SOURCE2 .= "
+ int globalDataBecameNonConst = 15;";
+
+ # Global_Data_Became_Const (safe)
+ $HEADER1 .= "
+ extern $DECL_SPEC int globalDataBecameConst;";
+ $SOURCE1 .= "
+ int globalDataBecameConst = 10;";
+
+ $HEADER2 .= "
+ $EXTERN $DECL_SPEC const int globalDataBecameConst=15;";
+
+ # Global_Data_Became_Non_Const (struct)
+ $HEADER1 .= "
+ struct GlobalDataType{int a;int b;struct GlobalDataType* p;};
+ $EXTERN $DECL_SPEC const struct GlobalDataType globalStructDataBecameConst = {1, 2, (struct GlobalDataType*)0};";
+
+ $HEADER2 .= "
+ struct GlobalDataType{int a;int b;struct GlobalDataType* p;};
+ $EXTERN $DECL_SPEC struct GlobalDataType globalStructDataBecameConst = {1, 2, (struct GlobalDataType*)0};";
+
+ # Removed_Parameter
+ $HEADER1 .= "
+ $DECL_SPEC int removedParameter(int param, int removed_param);";
+ $SOURCE1 .= "
+ int removedParameter(int param, int removed_param) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int removedParameter(int param);";
+ $SOURCE2 .= "
+ int removedParameter(int param) { return 0; }";
+
+ # Added_Parameter
+ $HEADER1 .= "
+ $DECL_SPEC int addedParameter(int param);";
+ $SOURCE1 .= "
+ int addedParameter(int param) { return param; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int addedParameter(int param, int added_param, int added_param2);";
+ $SOURCE2 .= "
+ int addedParameter(int param, int added_param, int added_param2) { return added_param2; }";
+
+ # Added_Interface (typedef to funcptr parameter)
+ $HEADER2 .= "
+ typedef int (*FUNCPTR_TYPE)(int a, int b);
+ $DECL_SPEC int addedFunc(FUNCPTR_TYPE*const** f);";
+ $SOURCE2 .= "
+ int addedFunc(FUNCPTR_TYPE*const** f) { return 0; }";
+
+ # Added_Interface (funcptr parameter)
+ $HEADER2 .= "
+ $DECL_SPEC int addedFunc2(int(*func)(int, int));";
+ $SOURCE2 .= "
+ int addedFunc2(int(*func)(int, int)) { return 0; }";
+
+ # Added_Interface (no limited parameters)
+ $HEADER2 .= "
+ $DECL_SPEC int addedFunc3(float p1, ...);";
+ $SOURCE2 .= "
+ int addedFunc3(float p1, ...) { return 0; }";
+
+ # Size
+ $HEADER1 .= "
+ struct TypeSize
+ {
+ long long i[5];
+ long j;
+ double k;
+ struct TypeSize* p;
+ };
+ $DECL_SPEC int testSize(struct TypeSize param, int param_2);";
+ $SOURCE1 .= "
+ int testSize(struct TypeSize param, int param_2) { return param_2; }";
+
+ $HEADER2 .= "
+ struct TypeSize
+ {
+ long long i[15];
+ long long j;
+ double k;
+ struct TypeSize* p;
+ };
+ $DECL_SPEC int testSize(struct TypeSize param, int param_2);";
+ $SOURCE2 .= "
+ int testSize(struct TypeSize param, int param_2) { return param_2; }";
+
+ # Added_Field_And_Size
+ $HEADER1 .= "
+ struct AddedFieldAndSize
+ {
+ int i;
+ long j;
+ double k;
+ struct AddedFieldAndSize* p;
+ };
+ $DECL_SPEC int addedFieldAndSize(struct AddedFieldAndSize param, int param_2);";
+ $SOURCE1 .= "
+ int addedFieldAndSize(struct AddedFieldAndSize param, int param_2) { return param_2; }";
+
+ $HEADER2 .= "
+ struct AddedFieldAndSize
+ {
+ int i;
+ long j;
+ double k;
+ struct AddedFieldAndSize* p;
+ int added_member1;
+ int added_member2;
+ };
+ $DECL_SPEC int addedFieldAndSize(struct AddedFieldAndSize param, int param_2);";
+ $SOURCE2 .= "
+ int addedFieldAndSize(struct AddedFieldAndSize param, int param_2) { return param_2; }";
+
+ # Added_Middle_Field_And_Size
+ $HEADER1 .= "
+ struct AddedMiddleFieldAndSize
+ {
+ int i;
+ long j;
+ double k;
+ struct AddedMiddleFieldAndSize* p;
+ };
+ $DECL_SPEC int addedMiddleFieldAndSize(struct AddedMiddleFieldAndSize param, int param_2);";
+ $SOURCE1 .= "
+ int addedMiddleFieldAndSize(struct AddedMiddleFieldAndSize param, int param_2) { return param_2; }";
+
+ $HEADER2 .= "
+ struct AddedMiddleFieldAndSize
+ {
+ int i;
+ int added_middle_member;
+ long j;
+ double k;
+ struct AddedMiddleFieldAndSize* p;
+ };
+ $DECL_SPEC int addedMiddleFieldAndSize(struct AddedMiddleFieldAndSize param, int param_2);";
+ $SOURCE2 .= "
+ int addedMiddleFieldAndSize(struct AddedMiddleFieldAndSize param, int param_2) { return param_2; }";
+
+ # Added_Middle_Field
+ $HEADER1 .= "
+ struct AddedMiddleField
+ {
+ unsigned char field1;
+ unsigned short field2;
+ };
+ $DECL_SPEC int addedMiddleField(struct AddedMiddleField param, int param_2);";
+ $SOURCE1 .= "
+ int addedMiddleField(struct AddedMiddleField param, int param_2) { return param_2; }";
+
+ $HEADER2 .= "
+ struct AddedMiddleField
+ {
+ unsigned char field1;
+ unsigned char added_field;
+ unsigned short field2;
+ };
+ $DECL_SPEC int addedMiddleField(struct AddedMiddleField param, int param_2);";
+ $SOURCE2 .= "
+ int addedMiddleField(struct AddedMiddleField param, int param_2) { return param_2; }";
+
+ # Renamed_Field
+ $HEADER1 .= "
+ struct RenamedField
+ {
+ long i;
+ long j;
+ double k;
+ struct RenamedField* p;
+ };
+ $DECL_SPEC int renamedField(struct RenamedField param, int param_2);";
+ $SOURCE1 .= "
+ int renamedField(struct RenamedField param, int param_2) { return param_2; }";
+
+ $HEADER2 .= "
+ struct RenamedField
+ {
+ long renamed_member;
+ long j;
+ double k;
+ struct RenamedField* p;
+ };
+ $DECL_SPEC int renamedField(struct RenamedField param, int param_2);";
+ $SOURCE2 .= "
+ int renamedField(struct RenamedField param, int param_2) { return param_2; }";
+
+ # Renamed_Field
+ $HEADER1 .= "
+ union RenamedUnionField
+ {
+ int renamed_from;
+ double j;
+ };
+ $DECL_SPEC int renamedUnionField(union RenamedUnionField param);";
+ $SOURCE1 .= "
+ int renamedUnionField(union RenamedUnionField param) { return 0; }";
+
+ $HEADER2 .= "
+ union RenamedUnionField
+ {
+ int renamed_to;
+ double j;
+ };
+ $DECL_SPEC int renamedUnionField(union RenamedUnionField param);";
+ $SOURCE2 .= "
+ int renamedUnionField(union RenamedUnionField param) { return 0; }";
+
+ # Removed_Field_And_Size
+ $HEADER1 .= "
+ struct RemovedFieldAndSize
+ {
+ int i;
+ long j;
+ double k;
+ struct RemovedFieldAndSize* p;
+ int removed_member1;
+ int removed_member2;
+ };
+ $DECL_SPEC int removedFieldAndSize(struct RemovedFieldAndSize param, int param_2);";
+ $SOURCE1 .= "
+ int removedFieldAndSize(struct RemovedFieldAndSize param, int param_2) { return param_2; }";
+
+ $HEADER2 .= "
+ struct RemovedFieldAndSize
+ {
+ int i;
+ long j;
+ double k;
+ struct RemovedFieldAndSize* p;
+ };
+ $DECL_SPEC int removedFieldAndSize(struct RemovedFieldAndSize param, int param_2);";
+ $SOURCE2 .= "
+ int removedFieldAndSize(struct RemovedFieldAndSize param, int param_2) { return param_2; }";
+
+ # Removed_Middle_Field
+ $HEADER1 .= "
+ struct RemovedMiddleField
+ {
+ int i;
+ int removed_middle_member;
+ long j;
+ double k;
+ struct RemovedMiddleField* p;
+ };
+ $DECL_SPEC int removedMiddleField(struct RemovedMiddleField param, int param_2);";
+ $SOURCE1 .= "
+ int removedMiddleField(struct RemovedMiddleField param, int param_2) { return param_2; }";
+
+ $HEADER2 .= "
+ struct RemovedMiddleField
+ {
+ int i;
+ long j;
+ double k;
+ struct RemovedMiddleField* p;
+ };
+ $DECL_SPEC int removedMiddleField(struct RemovedMiddleField param, int param_2);";
+ $SOURCE2 .= "
+ int removedMiddleField(struct RemovedMiddleField param, int param_2) { return param_2; }";
+
+ # Enum_Member_Value
+ $HEADER1 .= "
+ enum EnumMemberValue
+ {
+ MEMBER1=1,
+ MEMBER2=2
+ };
+ $DECL_SPEC int enumMemberValue(enum EnumMemberValue param);";
+ $SOURCE1 .= "
+ int enumMemberValue(enum EnumMemberValue param) { return 0; }";
+
+ $HEADER2 .= "
+ enum EnumMemberValue
+ {
+ MEMBER1=2,
+ MEMBER2=1
+ };
+ $DECL_SPEC int enumMemberValue(enum EnumMemberValue param);";
+ $SOURCE2 .= "
+ int enumMemberValue(enum EnumMemberValue param) { return 0; }";
+
+ # Enum_Member_Removed
+ $HEADER1 .= "
+ enum EnumMemberRemoved
+ {
+ MEMBER=1,
+ MEMBER_REMOVED=2
+ };
+ $DECL_SPEC int enumMemberRemoved(enum EnumMemberRemoved param);";
+ $SOURCE1 .= "
+ int enumMemberRemoved(enum EnumMemberRemoved param) { return 0; }";
+
+ $HEADER2 .= "
+ enum EnumMemberRemoved
+ {
+ MEMBER=1
+ };
+ $DECL_SPEC int enumMemberRemoved(enum EnumMemberRemoved param);";
+ $SOURCE2 .= "
+ int enumMemberRemoved(enum EnumMemberRemoved param) { return 0; }";
+
+ # Enum_Member_Removed (middle)
+ $HEADER1 .= "
+ enum EnumMiddleMemberRemoved
+ {
+ MEM_REMOVED,
+ MEM1,
+ MEM2
+ };
+ $DECL_SPEC int enumMiddleMemberRemoved(enum EnumMiddleMemberRemoved param);";
+ $SOURCE1 .= "
+ int enumMiddleMemberRemoved(enum EnumMiddleMemberRemoved param) { return 0; }";
+
+ $HEADER2 .= "
+ enum EnumMiddleMemberRemoved
+ {
+ MEM1,
+ MEM2
+ };
+ $DECL_SPEC int enumMiddleMemberRemoved(enum EnumMiddleMemberRemoved param);";
+ $SOURCE2 .= "
+ int enumMiddleMemberRemoved(enum EnumMiddleMemberRemoved param) { return 0; }";
+
+ # Enum_Member_Name
+ $HEADER1 .= "
+ enum EnumMemberName
+ {
+ BRANCH1=1,
+ BRANCH2=2
+ };
+ $DECL_SPEC int enumMemberName(enum EnumMemberName param);";
+ $SOURCE1 .= "
+ int enumMemberName(enum EnumMemberName param) { return 0; }";
+
+ $HEADER2 .= "
+ enum EnumMemberName
+ {
+ BRANCH_FIRST=1,
+ BRANCH_SECOND=2
+ };
+ $DECL_SPEC int enumMemberName(enum EnumMemberName param);";
+ $SOURCE2 .= "
+ int enumMemberName(enum EnumMemberName param) { return 0; }";
+
+ # Field_Type_And_Size
+ $HEADER1 .= "
+ struct FieldTypeAndSize
+ {
+ int i;
+ long j;
+ double k;
+ struct FieldTypeAndSize* p;
+ };
+ $DECL_SPEC int fieldTypeAndSize(struct FieldTypeAndSize param, int param_2);";
+ $SOURCE1 .= "
+ int fieldTypeAndSize(struct FieldTypeAndSize param, int param_2) { return param_2; }";
+
+ $HEADER2 .= "
+ struct FieldTypeAndSize
+ {
+ int i;
+ long long j;
+ double k;
+ struct FieldTypeAndSize* p;
+ };
+ $DECL_SPEC int fieldTypeAndSize(struct FieldTypeAndSize param, int param_2);";
+ $SOURCE2 .= "
+ int fieldTypeAndSize(struct FieldTypeAndSize param, int param_2) { return param_2; }";
+
+ # Field_Type
+ $HEADER1 .= "
+ struct FieldType
+ {
+ int i;
+ long j;
+ double k;
+ struct FieldType* p;
+ };
+ $DECL_SPEC int fieldType(struct FieldType param, int param_2);";
+ $SOURCE1 .= "
+ int fieldType(struct FieldType param, int param_2) { return param_2; }";
+
+ $HEADER2 .= "
+ struct FieldType
+ {
+ float i;
+ long j;
+ double k;
+ struct FieldType* p;
+ };
+ $DECL_SPEC int fieldType(struct FieldType param, int param_2);";
+ $SOURCE2 .= "
+ int fieldType(struct FieldType param, int param_2) { return param_2; }";
+
+ # Field_BaseType
+ $HEADER1 .= "
+ struct FieldBaseType
+ {
+ int i;
+ long *j;
+ double k;
+ struct FieldBaseType* p;
+ };
+ $DECL_SPEC int fieldBaseType(struct FieldBaseType param, int param_2);";
+ $SOURCE1 .= "
+ int fieldBaseType(struct FieldBaseType param, int param_2) { return param_2; }";
+
+ $HEADER2 .= "
+ struct FieldBaseType
+ {
+ int i;
+ long long *j;
+ double k;
+ struct FieldBaseType* p;
+ };
+ $DECL_SPEC int fieldBaseType(struct FieldBaseType param, int param_2);";
+ $SOURCE2 .= "
+ int fieldBaseType(struct FieldBaseType param, int param_2) { return param_2; }";
+
+ # Field_PointerLevel (and Size)
+ $HEADER1 .= "
+ struct FieldPointerLevelAndSize
+ {
+ int i;
+ long long j;
+ double k;
+ struct FieldPointerLevelAndSize* p;
+ };
+ $DECL_SPEC int fieldPointerLevelAndSize(struct FieldPointerLevelAndSize param, int param_2);";
+ $SOURCE1 .= "
+ int fieldPointerLevelAndSize(struct FieldPointerLevelAndSize param, int param_2) { return param_2; }";
+
+ $HEADER2 .= "
+ struct FieldPointerLevelAndSize
+ {
+ int i;
+ long long *j;
+ double k;
+ struct FieldPointerLevelAndSize* p;
+ };
+ $DECL_SPEC int fieldPointerLevelAndSize(struct FieldPointerLevelAndSize param, int param_2);";
+ $SOURCE2 .= "
+ int fieldPointerLevelAndSize(struct FieldPointerLevelAndSize param, int param_2) { return param_2; }";
+
+ # Field_PointerLevel
+ $HEADER1 .= "
+ struct FieldPointerLevel
+ {
+ int i;
+ long *j;
+ double k;
+ struct FieldPointerLevel* p;
+ };
+ $DECL_SPEC int fieldPointerLevel(struct FieldPointerLevel param, int param_2);";
+ $SOURCE1 .= "
+ int fieldPointerLevel(struct FieldPointerLevel param, int param_2) { return param_2; }";
+
+ $HEADER2 .= "
+ struct FieldPointerLevel
+ {
+ int i;
+ long **j;
+ double k;
+ struct FieldPointerLevel* p;
+ };
+ $DECL_SPEC int fieldPointerLevel(struct FieldPointerLevel param, int param_2);";
+ $SOURCE2 .= "
+ int fieldPointerLevel(struct FieldPointerLevel param, int param_2) { return param_2; }";
+
+ # Added_Interface
+ $HEADER2 .= "
+ $DECL_SPEC int addedFunc4(int param);";
+ $SOURCE2 .= "
+ int addedFunc4(int param) { return param; }";
+
+ # Removed_Interface
+ $HEADER1 .= "
+ $DECL_SPEC int removedFunc(int param);";
+ $SOURCE1 .= "
+ int removedFunc(int param) { return param; }";
+
+ # Parameter_Type_And_Size
+ $HEADER1 .= "
+ $DECL_SPEC int parameterTypeAndSize(int param, int other_param);";
+ $SOURCE1 .= "
+ int parameterTypeAndSize(int param, int other_param) { return other_param; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int parameterTypeAndSize(long long param, int other_param);";
+ $SOURCE2 .= "
+ int parameterTypeAndSize(long long param, int other_param) { return other_param; }";
+
+ # Parameter_Type_And_Size (test calling conventions)
+ $HEADER1 .= "\n
+ $DECL_SPEC int parameterCallingConvention(int p1, int p2, int p3);";
+ $SOURCE1 .= "
+ int parameterCallingConvention(int p1, int p2, int p3) { return 0; }";
+
+ $HEADER2 .= "\n
+ $DECL_SPEC float parameterCallingConvention(char p1, int p2, int p3);";
+ $SOURCE2 .= "
+ float parameterCallingConvention(char p1, int p2, int p3) { return 7.0f; }";
+
+ # Parameter_Type
+ $HEADER1 .= "
+ $DECL_SPEC int parameterType(int param, int other_param);";
+ $SOURCE1 .= "
+ int parameterType(int param, int other_param) { return other_param; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int parameterType(float param, int other_param);";
+ $SOURCE2 .= "
+ int parameterType(float param, int other_param) { return other_param; }";
+
+ # Parameter_Became_Non_Const
+ $HEADER1 .= "
+ $DECL_SPEC int parameterBecameNonConst(int const* param);";
+ $SOURCE1 .= "
+ int parameterBecameNonConst(int const* param) { return *param; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int parameterBecameNonConst(int* param);";
+ $SOURCE2 .= "
+ int parameterBecameNonConst(int* param) {
+ *param=10;
+ return *param;
+ }";
+
+ # Parameter_BaseType (Typedef)
+ $HEADER1 .= "
+ typedef int* PARAM_TYPEDEF;
+ $DECL_SPEC int parameterBaseTypedefChange(PARAM_TYPEDEF param);";
+ $SOURCE1 .= "
+ int parameterBaseTypedefChange(PARAM_TYPEDEF param) { return 0; }";
+
+ $HEADER2 .= "
+ typedef const int* PARAM_TYPEDEF;
+ $DECL_SPEC int parameterBaseTypedefChange(PARAM_TYPEDEF param);";
+ $SOURCE2 .= "
+ int parameterBaseTypedefChange(PARAM_TYPEDEF param) { return 0; }";
+
+ # Parameter_BaseType
+ $HEADER1 .= "
+ $DECL_SPEC int parameterBaseTypeChange(int *param);";
+ $SOURCE1 .= "
+ int parameterBaseTypeChange(int *param) { return sizeof(*param); }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int parameterBaseTypeChange(long long *param);";
+ $SOURCE2 .= "
+ int parameterBaseTypeChange(long long *param) { return sizeof(*param); }";
+
+ # Parameter_PointerLevel
+ $HEADER1 .= "
+ $DECL_SPEC long long parameterPointerLevelAndSize(long long param);";
+ $SOURCE1 .= "
+ long long parameterPointerLevelAndSize(long long param) { return param; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC long long parameterPointerLevelAndSize(long long *param);";
+ $SOURCE2 .= "
+ long long parameterPointerLevelAndSize(long long *param) { return param[5]; }";
+
+ # Parameter_PointerLevel
+ $HEADER1 .= "
+ $DECL_SPEC int parameterPointerLevel(int *param);";
+ $SOURCE1 .= "
+ int parameterPointerLevel(int *param) { return param[5]; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int parameterPointerLevel(int **param);";
+ $SOURCE2 .= "
+ int parameterPointerLevel(int **param) { return param[5][5]; }";
+
+ # Return_Type_And_Size
+ $HEADER1 .= "
+ $DECL_SPEC int returnTypeAndSize(int param);";
+ $SOURCE1 .= "
+ int returnTypeAndSize(int param) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC long long returnTypeAndSize(int param);";
+ $SOURCE2 .= "
+ long long returnTypeAndSize(int param) { return 0; }";
+
+ # Return_Type
+ $HEADER1 .= "
+ $DECL_SPEC int returnType(int param);";
+ $SOURCE1 .= "
+ int returnType(int param) { return 1; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC float returnType(int param);";
+ $SOURCE2 .= "
+ float returnType(int param) { return 1; }";
+
+ # Return_Type_Became_Void ("int" to "void")
+ $HEADER1 .= "
+ $DECL_SPEC int returnTypeChangeToVoid(int param);";
+ $SOURCE1 .= "
+ int returnTypeChangeToVoid(int param) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC void returnTypeChangeToVoid(int param);";
+ $SOURCE2 .= "
+ void returnTypeChangeToVoid(int param) { return; }";
+
+ # Return_Type ("struct" to "void*")
+ $HEADER1 .= "
+ struct SomeStruct {int A;long B;};
+ $DECL_SPEC struct SomeStruct* returnTypeChangeToVoidPtr(int param);";
+ $SOURCE1 .= "
+ struct SomeStruct* returnTypeChangeToVoidPtr(int param) { return (struct SomeStruct*)0; }";
+
+ $HEADER2 .= "
+ struct SomeStruct {int A;int B;};
+ $DECL_SPEC void* returnTypeChangeToVoidPtr(int param);";
+ $SOURCE2 .= "
+ void* returnTypeChangeToVoidPtr(int param) { return (void*)0; }";
+
+ # Return_Type_From_Void_And_Stack_Layout ("void" to "struct")
+ $HEADER1 .= "
+ $DECL_SPEC void returnTypeChangeFromVoidToStruct(int param);";
+ $SOURCE1 .= "
+ void returnTypeChangeFromVoidToStruct(int param) { return; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC struct SomeStruct returnTypeChangeFromVoidToStruct(int param);";
+ $SOURCE2 .= "
+ struct SomeStruct returnTypeChangeFromVoidToStruct(int param) {
+ struct SomeStruct obj = {1,2};
+ return obj;
+ }";
+
+ # Return_Type_Became_Void_And_Stack_Layout ("struct" to "void")
+ $HEADER1 .= "
+ $DECL_SPEC struct SomeStruct returnTypeChangeFromStructToVoid(int param);";
+ $SOURCE1 .= "
+ struct SomeStruct returnTypeChangeFromStructToVoid(int param) {
+ struct SomeStruct obj = {1,2};
+ return obj;
+ }";
+
+ $HEADER2 .= "
+ $DECL_SPEC void returnTypeChangeFromStructToVoid(int param);";
+ $SOURCE2 .= "
+ void returnTypeChangeFromStructToVoid(int param) { return; }";
+
+ # Return_Type_From_Void_And_Stack_Layout (safe, "void" to "long")
+ $HEADER1 .= "
+ $DECL_SPEC void returnTypeChangeFromVoidToLong(int param);";
+ $SOURCE1 .= "
+ void returnTypeChangeFromVoidToLong(int param) { return; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC long returnTypeChangeFromVoidToLong(int param);";
+ $SOURCE2 .= "
+ long returnTypeChangeFromVoidToLong(int param) { return 0; }";
+
+ # Return_Type_From_Register_To_Stack ("int" to "struct")
+ $HEADER1 .= "
+ $DECL_SPEC int returnTypeChangeFromIntToStruct(int param);";
+ $SOURCE1 .= "
+ int returnTypeChangeFromIntToStruct(int param) { return param; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC struct SomeStruct returnTypeChangeFromIntToStruct(int param);";
+ $SOURCE2 .= "
+ struct SomeStruct returnTypeChangeFromIntToStruct(int param) {
+ struct SomeStruct obj = {1,2};
+ return obj;
+ }";
+
+ # Return_Type_From_Stack_To_Register (from struct to int)
+ $HEADER1 .= "
+ $DECL_SPEC struct SomeStruct returnTypeChangeFromStructToInt(int param);";
+ $SOURCE1 .= "
+ struct SomeStruct returnTypeChangeFromStructToInt(int param) {
+ struct SomeStruct obj = {1,2};
+ return obj;
+ }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int returnTypeChangeFromStructToInt(int param);";
+ $SOURCE2 .= "
+ int returnTypeChangeFromStructToInt(int param) { return param; }";
+
+ # Return_Type_From_Stack_To_Register (from struct to int, without parameters)
+ $HEADER1 .= "
+ $DECL_SPEC struct SomeStruct returnTypeChangeFromStructToIntWithNoParams();";
+ $SOURCE1 .= "
+ struct SomeStruct returnTypeChangeFromStructToIntWithNoParams() {
+ struct SomeStruct obj = {1,2};
+ return obj;
+ }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int returnTypeChangeFromStructToIntWithNoParams();";
+ $SOURCE2 .= "
+ int returnTypeChangeFromStructToIntWithNoParams() { return 0; }";
+
+ # Return_BaseType
+ $HEADER1 .= "
+ $DECL_SPEC int *returnBaseTypeChange(int param);";
+ $SOURCE1 .= "
+ int *returnBaseTypeChange(int param) { return (int*)0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC long long *returnBaseTypeChange(int param);";
+ $SOURCE2 .= "
+ long long *returnBaseTypeChange(int param) { return (long long*)0; }";
+
+ # Return_PointerLevel
+ $HEADER1 .= "
+ $DECL_SPEC long long returnPointerLevelAndSize(int param);";
+ $SOURCE1 .= "
+ long long returnPointerLevelAndSize(int param) { return 100; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC long long *returnPointerLevelAndSize(int param);";
+ $SOURCE2 .= "
+ long long *returnPointerLevelAndSize(int param) { return (long long *)0; }";
+
+ # Return_PointerLevel
+ $HEADER1 .= "
+ $DECL_SPEC long long *returnPointerLevel(int param);";
+ $SOURCE1 .= "
+ long long *returnPointerLevel(int param) { return (long long *)0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC long long **returnPointerLevel(int param);";
+ $SOURCE2 .= "
+ long long **returnPointerLevel(int param) { return (long long **)0; }";
+
+ # Size (typedef to anon structure)
+ $HEADER1 .= "
+ typedef struct
+ {
+ int i;
+ long j;
+ double k;
+ } AnonTypedef;
+ $DECL_SPEC int anonTypedef(AnonTypedef param);";
+ $SOURCE1 .= "
+ int anonTypedef(AnonTypedef param) { return 0; }";
+
+ $HEADER2 .= "
+ typedef struct
+ {
+ int i;
+ long j;
+ double k;
+ union {
+ int dummy[256];
+ struct {
+ char q_skiptable[256];
+ const char *p;
+ int l;
+ } p;
+ };
+ } AnonTypedef;
+ $DECL_SPEC int anonTypedef(AnonTypedef param);";
+ $SOURCE2 .= "
+ int anonTypedef(AnonTypedef param) { return 0; }";
+
+ # Size (safe: opaque)
+ $HEADER1 .= "
+ struct OpaqueType
+ {
+ long long i[5];
+ long j;
+ double k;
+ struct OpaqueType* p;
+ };
+ $DECL_SPEC int opaqueTypeUse(struct OpaqueType param, int param_2);";
+ $SOURCE1 .= "
+ int opaqueTypeUse(struct OpaqueType param, int param_2) { return param_2; }";
+
+ $HEADER2 .= "
+ struct OpaqueType
+ {
+ long long i[5];
+ long long j;
+ double k;
+ struct OpaqueType* p;
+ };
+ $DECL_SPEC int opaqueTypeUse(struct OpaqueType param, int param_2);";
+ $SOURCE2 .= "
+ int opaqueTypeUse(struct OpaqueType param, int param_2) { return param_2; }";
+
+ # Size (safe: internal)
+ $HEADER1 .= "
+ struct InternalType
+ {
+ long long i[5];
+ long j;
+ double k;
+ struct InternalType* p;
+ };
+ $DECL_SPEC int internalTypeUse(struct InternalType param, int param_2);";
+ $SOURCE1 .= "
+ int internalTypeUse(struct InternalType param, int param_2) { return param_2; }";
+
+ $HEADER2 .= "
+ struct InternalType
+ {
+ long long i[5];
+ long long j;
+ double k;
+ struct InternalType* p;
+ };
+ $DECL_SPEC int internalTypeUse(struct InternalType param, int param_2);";
+ $SOURCE2 .= "
+ int internalTypeUse(struct InternalType param, int param_2) { return param_2; }";
+
+ if($OSgroup eq "linux")
+ {
+ # Changed version
+ $HEADER1 .= "
+ $DECL_SPEC int changedVersion(int param);
+ $DECL_SPEC int changedDefaultVersion(int param);";
+ $SOURCE1 .= "
+ int changedVersion(int param) { return 0; }
+ __asm__(\".symver changedVersion,changedVersion\@VERSION_2.0\");
+ int changedDefaultVersion(int param) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int changedVersion(int param);
+ $DECL_SPEC int changedDefaultVersion(long param);";
+ $SOURCE2 .= "
+ int changedVersion(int param) { return 0; }
+ __asm__(\".symver changedVersion,changedVersion\@VERSION_3.0\");
+ int changedDefaultVersion(long param) { return 0; }";
+
+ # Unchanged version
+ $HEADER1 .= "
+ $DECL_SPEC int unchangedVersion(int param);
+ $DECL_SPEC int unchangedDefaultVersion(int param);";
+ $SOURCE1 .= "
+ int unchangedVersion(int param) { return 0; }
+ __asm__(\".symver unchangedVersion,unchangedVersion\@VERSION_1.0\");
+ int unchangedDefaultVersion(int param) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int unchangedVersion(int param);
+ $DECL_SPEC int unchangedDefaultVersion(int param);";
+ $SOURCE2 .= "
+ int unchangedVersion(int param) { return 0; }
+ __asm__(\".symver unchangedVersion,unchangedVersion\@VERSION_1.0\");
+ int unchangedDefaultVersion(int param) { return 0; }";
+
+ # Non-Default to Default
+ $HEADER1 .= "
+ $DECL_SPEC int changedVersionToDefault(int param);";
+ $SOURCE1 .= "
+ int changedVersionToDefault(int param) { return 0; }
+ __asm__(\".symver changedVersionToDefault,changedVersionToDefault\@VERSION_1.0\");";
+
+ $HEADER2 .= "
+ $DECL_SPEC int changedVersionToDefault(long param);";
+ $SOURCE2 .= "
+ int changedVersionToDefault(long param) { return 0; }";
+
+ # Default to Non-Default
+ $HEADER1 .= "
+ $DECL_SPEC int changedVersionToNonDefault(int param);";
+ $SOURCE1 .= "
+ int changedVersionToNonDefault(int param) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int changedVersionToNonDefault(long param);";
+ $SOURCE2 .= "
+ int changedVersionToNonDefault(long param) { return 0; }
+ __asm__(\".symver changedVersionToNonDefault,changedVersionToNonDefault\@VERSION_3.0\");";
+
+ # Added version
+ $HEADER1 .= "
+ $DECL_SPEC int addedVersion(int param);
+ $DECL_SPEC int addedDefaultVersion(int param);";
+ $SOURCE1 .= "
+ int addedVersion(int param) { return 0; }
+ int addedDefaultVersion(int param) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int addedVersion(int param);
+ $DECL_SPEC int addedDefaultVersion(int param);";
+ $SOURCE2 .= "
+ int addedVersion(int param) { return 0; }
+ __asm__(\".symver addedVersion,addedVersion\@VERSION_2.0\");
+ int addedDefaultVersion(int param) { return 0; }";
+
+ # Removed version
+ $HEADER1 .= "
+ $DECL_SPEC int removedVersion(int param);
+ $DECL_SPEC int removedVersion2(int param);
+ $DECL_SPEC int removedDefaultVersion(int param);";
+ $SOURCE1 .= "
+ int removedVersion(int param) { return 0; }
+ __asm__(\".symver removedVersion,removedVersion\@VERSION_1.0\");
+ int removedVersion2(int param) { return 0; }
+ __asm__(\".symver removedVersion2,removedVersion\@VERSION_3.0\");
+ int removedDefaultVersion(int param) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int removedVersion(int param);
+ $DECL_SPEC int removedVersion2(int param);
+ $DECL_SPEC int removedDefaultVersion(int param);";
+ $SOURCE2 .= "
+ int removedVersion(int param) { return 0; }
+ int removedVersion2(int param) { return 0; }
+ __asm__(\".symver removedVersion2,removedVersion\@VERSION_3.0\");
+ int removedDefaultVersion(int param) { return 0; }";
+
+ # Return_Type (good versioning)
+ $HEADER1 .= "
+ $DECL_SPEC int goodVersioning(int param);";
+ $SOURCE1 .= "
+ int goodVersioning(int param) { return 0; }
+ __asm__(\".symver goodVersioning,goodVersioning\@VERSION_1.0\");";
+
+ $HEADER2 .= "
+ $DECL_SPEC int goodVersioningOld(int param);";
+ $SOURCE2 .= "
+ int goodVersioningOld(int param) { return 0; }
+ __asm__(\".symver goodVersioningOld,goodVersioning\@VERSION_1.0\");";
+
+ $HEADER2 .= "
+ $DECL_SPEC float goodVersioning(int param);";
+ $SOURCE2 .= "
+ float goodVersioning(int param) { return 0.7; }
+ __asm__(\".symver goodVersioning,goodVersioning\@VERSION_2.0\");";
+
+ # Return_Type (bad versioning)
+ $HEADER1 .= "
+ $DECL_SPEC int badVersioning(int param);";
+ $SOURCE1 .= "
+ int badVersioning(int param) { return 0; }
+ __asm__(\".symver badVersioning,badVersioning\@VERSION_1.0\");";
+
+ $HEADER2 .= "
+ $DECL_SPEC float badVersioningOld(int param);";
+ $SOURCE2 .= "
+ float badVersioningOld(int param) { return 0.7; }
+ __asm__(\".symver badVersioningOld,badVersioning\@VERSION_1.0\");";
+
+ $HEADER2 .= "
+ $DECL_SPEC float badVersioning(int param);";
+ $SOURCE2 .= "
+ float badVersioning(int param) { return 0.7; }
+ __asm__(\".symver badVersioning,badVersioning\@VERSION_2.0\");";
+ }
+ # unnamed struct/union fields within structs/unions
+ $HEADER1 .= "
+ typedef struct
+ {
+ int a;
+ union {
+ int b;
+ float c;
+ };
+ int d;
+ } UnnamedTypeSize;
+ $DECL_SPEC int unnamedTypeSize(UnnamedTypeSize param);";
+ $SOURCE1 .= "
+ int unnamedTypeSize(UnnamedTypeSize param) { return 0; }";
+
+ $HEADER2 .= "
+ typedef struct
+ {
+ int a;
+ union {
+ long double b;
+ float c;
+ };
+ int d;
+ } UnnamedTypeSize;
+ $DECL_SPEC int unnamedTypeSize(UnnamedTypeSize param);";
+ $SOURCE2 .= "
+ int unnamedTypeSize(UnnamedTypeSize param) { return 0; }";
+
+ # Changed_Constant
+ $HEADER1 .= "
+ #define PUBLIC_CONSTANT \"old_value\"";
+ $HEADER2 .= "
+ #define PUBLIC_CONSTANT \"new_value\"";
+
+ # Changed_Constant (Safe)
+ $HEADER1 .= "
+ #define INTEGER_CONSTANT 0x01";
+ $HEADER2 .= "
+ #define INTEGER_CONSTANT 1";
+
+ # Changed_Constant (Safe)
+ $HEADER1 .= "
+ #define PRIVATE_CONSTANT \"old_value\"
+ #undef PRIVATE_CONSTANT";
+ $HEADER2 .= "
+ #define PRIVATE_CONSTANT \"new_value\"
+ #undef PRIVATE_CONSTANT";
+
+ # Added_Field (union)
+ $HEADER1 .= "
+ union UnionTypeAddedField
+ {
+ int a;
+ struct {
+ int b;
+ float c;
+ };
+ int d;
+ };
+ $DECL_SPEC int unionTypeAddedField(union UnionTypeAddedField param);";
+ $SOURCE1 .= "
+ int unionTypeAddedField(union UnionTypeAddedField param) { return 0; }";
+
+ $HEADER2 .= "
+ union UnionTypeAddedField
+ {
+ int a;
+ struct {
+ long double x, y;
+ } new_field;
+ struct {
+ int b;
+ float c;
+ };
+ int d;
+ };
+ $DECL_SPEC int unionTypeAddedField(union UnionTypeAddedField param);";
+ $SOURCE2 .= "
+ int unionTypeAddedField(union UnionTypeAddedField param) { return 0; }";
+
+ # Prameter_BaseType (typedef)
+ $HEADER1 .= "
+ typedef float TYPEDEF_TYPE;
+ $DECL_SPEC int parameterTypedefChange(TYPEDEF_TYPE param);";
+ $SOURCE1 .= "
+ int parameterTypedefChange(TYPEDEF_TYPE param) { return 1.0; }";
+
+ $HEADER2 .= "
+ typedef int TYPEDEF_TYPE;
+ $DECL_SPEC int parameterTypedefChange(TYPEDEF_TYPE param);";
+ $SOURCE2 .= "
+ int parameterTypedefChange(TYPEDEF_TYPE param) { return 1; }";
+
+ # Field_BaseType (typedef in member type)
+ $HEADER1 .= "
+ typedef float TYPEDEF_TYPE_2;
+ struct FieldBaseTypedefChange {
+ TYPEDEF_TYPE_2 m;
+ };
+ $DECL_SPEC int fieldBaseTypedefChange(struct FieldBaseTypedefChange param);";
+ $SOURCE1 .= "
+ int fieldBaseTypedefChange(struct FieldBaseTypedefChange param) { return 1; }";
+
+ $HEADER2 .= "
+ typedef int TYPEDEF_TYPE_2;
+ struct FieldBaseTypedefChange {
+ TYPEDEF_TYPE_2 m;
+ };
+ $DECL_SPEC int fieldBaseTypedefChange(struct FieldBaseTypedefChange param);";
+ $SOURCE2 .= "
+ int fieldBaseTypedefChange(struct FieldBaseTypedefChange param) { return 1; }";
+
+ # C++ keywords in C code
+ $HEADER1 .= "
+ $DECL_SPEC int testCppKeywords1(int class, int virtual, int (*new)(int));";
+ $SOURCE1 .= "
+ $DECL_SPEC int testCppKeywords1(int class, int virtual, int (*new)(int)) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int testCppKeywords1(int class, int virtual);
+ $DECL_SPEC int testCppKeywords2(int operator, int other);
+ $DECL_SPEC int testCppKeywords3(int operator);
+ $DECL_SPEC int operator(int class, int this);
+ $DECL_SPEC int delete(int virtual, int* this);
+ struct CppKeywords {
+ int bool: 8;
+ //int*this;
+ };
+ #ifdef __cplusplus
+ class TestCppKeywords {
+ void operator delete(void*);
+ void operator ()(int);
+ void operator,(int);
+ void delete() {
+ delete this;
+ };
+ };
+ #endif";
+ $SOURCE2 .= "
+ $DECL_SPEC int testCppKeywords(int class, int virtual) { return 0; }";
+
+ # Regression
+ $HEADER1 .= "
+ $DECL_SPEC int* testRegression(int *pointer, char const *name, ...);";
+ $SOURCE1 .= "
+ int* testRegression(int *pointer, char const *name, ...) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int* testRegression(int *pointer, char const *name, ...);";
+ $SOURCE2 .= "
+ int* testRegression(int *pointer, char const *name, ...) { return 0; }";
+
+ runTests("libsample_c", "C", $HEADER1, $SOURCE1, $HEADER2, $SOURCE2, "OpaqueType", "internalTypeUse");
+}
+
+sub runTests($$$$$$$$)
+{
+ my ($LibName, $Lang, $HEADER1, $SOURCE1, $HEADER2, $SOURCE2, $Opaque, $Private) = @_;
+ my $Ext = ($Lang eq "C++")?"cpp":"c";
+ rmtree($LibName);
+ # creating test suite
+ my $Path_v1 = "$LibName/libsample.v1";
+ my $Path_v2 = "$LibName/libsample.v2";
+ mkpath($Path_v1);
+ mkpath($Path_v2);
+ writeFile("$Path_v1/libsample.h", $HEADER1."\n");
+ writeFile("$Path_v1/libsample.$Ext", "#include \"libsample.h\"\n".$SOURCE1."\n");
+ writeFile("$LibName/v1.xml", "
+ <version>
+ 1.0
+ </version>
+
+ <headers>
+ ".get_abs_path($Path_v1)."
+ </headers>
+
+ <libs>
+ ".get_abs_path($Path_v1)."
+ </libs>
+
+ <skip_types>
+ $Opaque
+ </skip_types>
+
+ <skip_symbols>
+ $Private
+ </skip_symbols>
+
+ <include_paths>
+ ".get_abs_path($Path_v1)."
+ </include_paths>\n");
+ writeFile("$Path_v1/test.$Ext", "
+ #include \"libsample.h\"
+ #include <stdio.h>
+ ".($Lang eq "C++"?"using namespace TestNS;":"")."
+ int main()
+ {
+ int ret = 0;
+ printf(\"\%d\\n\", ret);
+ return 0;
+ }\n");
+
+ writeFile("$Path_v2/libsample.h", $HEADER2."\n");
+ writeFile("$Path_v2/libsample.$Ext", "#include \"libsample.h\"\n".$SOURCE2."\n");
+ writeFile("$LibName/v2.xml", "
+ <version>
+ 2.0
+ </version>
+
+ <headers>
+ ".get_abs_path($Path_v2)."
+ </headers>
+
+ <libs>
+ ".get_abs_path($Path_v2)."
+ </libs>
+
+ <skip_types>
+ $Opaque
+ </skip_types>
+
+ <skip_symbols>
+ $Private
+ </skip_symbols>
+
+ <include_paths>
+ ".get_abs_path($Path_v2)."
+ </include_paths>\n");
+ writeFile("$Path_v2/test.$Ext", "
+ #include \"libsample.h\"
+ #include <stdio.h>
+ ".($Lang eq "C++"?"using namespace TestNS;":"")."
+ int main()
+ {
+ int ret = 0;
+ printf(\"\%d\\n\", ret);
+ return 0;
+ }\n");
+
+ my ($BuildCmd, $BuildCmd_Test) = ("", "");
+ if($OSgroup eq "windows")
+ {
+ check_win32_env(); # to run MS VC++ compiler
+ my $CL = get_CmdPath("cl");
+ if(not $CL) {
+ exitStatus("Not_Found", "can't find \"cl\" compiler");
+ }
+ $BuildCmd = "$CL /LD libsample.$Ext >build_log.txt 2>&1";
+ $BuildCmd_Test = "$CL test.$Ext libsample.$LIB_EXT";
+ }
+ elsif($OSgroup eq "linux")
+ {
+ if($Lang eq "C")
+ { # tests for symbol versioning
+ writeFile("$Path_v1/version", "
+ VERSION_1.0 {
+ unchangedDefaultVersion;
+ removedDefaultVersion;
+ };
+ VERSION_2.0 {
+ changedDefaultVersion;
+ };
+ VERSION_3.0 {
+ changedVersionToNonDefault;
+ };
+ ");
+ writeFile("$Path_v2/version", "
+ VERSION_1.0 {
+ unchangedDefaultVersion;
+ changedVersionToDefault;
+ };
+ VERSION_2.0 {
+ addedDefaultVersion;
+ };
+ VERSION_3.0 {
+ changedDefaultVersion;
+ };
+ ");
+ $BuildCmd = $GCC_PATH." -Wl,--version-script version -shared -fkeep-inline-functions libsample.$Ext -o libsample.$LIB_EXT";
+ $BuildCmd_Test = $GCC_PATH." -Wl,--version-script version test.$Ext -Wl,libsample.$LIB_EXT -o test";
+ }
+ else
+ {
+ $BuildCmd = $GCC_PATH." -shared -fkeep-inline-functions -x c++ libsample.$Ext -lstdc++ -o libsample.$LIB_EXT";
+ $BuildCmd_Test = $GCC_PATH." -x c++ test.$Ext -lstdc++ -Wl,libsample.$LIB_EXT -o test";
+ }
+ if(getArch(1)=~/\A(arm|x86_64)\Z/i)
+ { # relocation R_ARM_MOVW_ABS_NC against `a local symbol' can not be used when making a shared object; recompile with -fPIC
+ $BuildCmd .= " -fPIC";
+ $BuildCmd_Test .= " -fPIC";
+ }
+ }
+ elsif($OSgroup eq "macos")
+ { # using GCC -dynamiclib
+ if($Lang eq "C")
+ {
+ $BuildCmd = $GCC_PATH." -dynamiclib -fkeep-inline-functions libsample.$Ext -o libsample.$LIB_EXT";
+ $BuildCmd_Test = $GCC_PATH." test.$Ext libsample.$LIB_EXT -o test";
+ }
+ else
+ { # C++
+ $BuildCmd = $GCC_PATH." -dynamiclib -fkeep-inline-functions -x c++ libsample.$Ext -lstdc++ -o libsample.$LIB_EXT";
+ $BuildCmd_Test = $GCC_PATH." -x c++ test.$Ext libsample.$LIB_EXT -o test";
+ }
+ }
+ else
+ { # default unix-like
+ # symbian target
+ if($Lang eq "C")
+ {
+ $BuildCmd = $GCC_PATH." -shared -fkeep-inline-functions libsample.$Ext -o libsample.$LIB_EXT";
+ $BuildCmd_Test = $GCC_PATH." test.$Ext -Wl,libsample.$LIB_EXT -o test";
+ }
+ else
+ { # C++
+ $BuildCmd = $GCC_PATH." -shared -fkeep-inline-functions -x c++ libsample.$Ext -lstdc++ -o libsample.$LIB_EXT";
+ $BuildCmd_Test = $GCC_PATH." -x c++ test.$Ext -Wl,libsample.$LIB_EXT -o test";
+ }
+ }
+ my $MkContent = "all:\n\t$BuildCmd\ntest:\n\t$BuildCmd_Test\n";
+ if($OSgroup eq "windows") {
+ $MkContent .= "clean:\n\tdel test libsample.so\n";
+ }
+ else {
+ $MkContent .= "clean:\n\trm test libsample.so\n";
+ }
+ writeFile("$Path_v1/Makefile", $MkContent);
+ writeFile("$Path_v2/Makefile", $MkContent);
+ system("cd $Path_v1 && $BuildCmd >build-log.txt 2>&1");
+ if($?) {
+ exitStatus("Error", "can't compile \'$Path_v1/libsample.$Ext\'");
+ }
+ system("cd $Path_v2 && $BuildCmd >build-log.txt 2>&1");
+ if($?) {
+ exitStatus("Error", "can't compile \'$Path_v2/libsample.$Ext\'");
+ }
+ # running the tool
+ my @Cmd = ("perl", $0, "-l", $LibName, "-d1", "$LibName/v1.xml", "-d2", "$LibName/v2.xml");
+ if($TestDump) {
+ @Cmd = (@Cmd, "-use-dumps");
+ }
+ if($GCC_PATH ne "gcc") {
+ @Cmd = (@Cmd, "-cross-gcc", $GCC_PATH);
+ }
+ if($Quiet)
+ { # quiet mode
+ @Cmd = (@Cmd, "-quiet");
+ }
+ if($ExtendedCheck)
+ { # extended mode
+ @Cmd = (@Cmd, "-extended");
+ if($Lang eq "C") {
+ @Cmd = (@Cmd, "-lang", "C");
+ }
+ }
+ if($LogMode eq "n") {
+ @Cmd = (@Cmd, "-logging-mode", "n");
+ }
+ elsif($Quiet) {
+ @Cmd = (@Cmd, "-logging-mode", "a");
+ }
+ if($ReportFormat) {
+ @Cmd = (@Cmd, "-report-format", $ReportFormat);
+ }
+ if($Debug)
+ { # debug mode
+ @Cmd = (@Cmd, "-debug");
+ printMsg("INFO", "@Cmd");
+ }
+ system(@Cmd);
+ my $RPath = "compat_reports/$LibName/1.0_to_2.0/abi_compat_report.$ReportFormat";
+ my $NProblems = 0;
+ if($ReportFormat eq "xml")
+ {
+ my $Content = readFile($RPath);
+ if(my $PSummary = parseTag(\$Content, "problem_summary"))
+ {
+ $NProblems += int(parseTag(\$PSummary, "removed_symbols"));
+ if(my $TProblems = parseTag(\$PSummary, "problems_with_types"))
+ {
+ $NProblems += int(parseTag(\$TProblems, "high"));
+ $NProblems += int(parseTag(\$TProblems, "medium"));
+ }
+ if(my $IProblems = parseTag(\$PSummary, "problems_with_symbols"))
+ {
+ $NProblems += int(parseTag(\$IProblems, "high"));
+ $NProblems += int(parseTag(\$IProblems, "medium"));
+ }
+ }
+ }
+ else
+ {
+ my $MetaData = readAttributes($RPath);
+ $NProblems += $MetaData->{"removed"};
+ $NProblems += $MetaData->{"type_problems_high"}+$MetaData->{"type_problems_medium"};
+ $NProblems += $MetaData->{"interface_problems_high"}+$MetaData->{"interface_problems_medium"};
+ }
+ if(($LibName eq "libsample_c" and $NProblems>30)
+ or ($LibName eq "libsample_cpp" and $NProblems>60)) {
+ printMsg("INFO", "result: SUCCESS ($NProblems problems found)\n");
+ }
+ else {
+ printMsg("ERROR", "result: FAILED ($NProblems problems found)\n");
+ }
+}
+
+return 1; \ No newline at end of file
diff --git a/modules/Internals/.svn/text-base/SysCheck.pm.svn-base b/modules/Internals/.svn/text-base/SysCheck.pm.svn-base
new file mode 100644
index 0000000..c4871bc
--- /dev/null
+++ b/modules/Internals/.svn/text-base/SysCheck.pm.svn-base
@@ -0,0 +1,1730 @@
+###########################################################################
+# Module for ABI Compliance Checker to compare Operating Systems
+#
+# Copyright (C) 2009-2010 The Linux Foundation.
+# Copyright (C) 2009-2011 Institute for System Programming, RAS.
+# Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+# Copyright (C) 2011 ROSA Laboratory.
+#
+# Written by Andrey Ponomarenko
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License or the GNU Lesser
+# General Public License as published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# and the GNU Lesser General Public License along with this program.
+# If not, see <http://www.gnu.org/licenses/>.
+###########################################################################
+use strict;
+use File::Temp qw(tempdir);
+use Cwd qw(abs_path cwd);
+
+my ($Debug, $Quiet, $LogMode, $CheckHeadersOnly, $SystemRoot, $MODULES_DIR, $GCC_PATH,
+$CrossPrefix, $TargetSysInfo, $TargetLibraryName, $CrossGcc, $UseStaticLibs, $NoStdInc, $OStarget);
+my $OSgroup = get_OSgroup();
+my $TMP_DIR = tempdir(CLEANUP=>1);
+my $ORIG_DIR = cwd();
+my $LIB_EXT = getLIB_EXT($OSgroup);
+
+my %SysDescriptor;
+my %Cache;
+
+sub cmpSystems($$$)
+{ # -cmp-systems option handler
+ # should be used with -d1 and -d2 options
+ my ($SPath1, $SPath2, $Opts) = @_;
+ readOpts($Opts);
+ if(not $SPath1) {
+ exitStatus("Error", "the option -d1 should be specified");
+ }
+ elsif(not -d $SPath1) {
+ exitStatus("Access_Error", "can't access directory \'".$SPath1."\'");
+ }
+ elsif(not -d $SPath1."/abi_dumps") {
+ exitStatus("Access_Error", "can't access directory \'".$SPath1."/abi_dumps\'");
+ }
+ if(not $SPath2) {
+ exitStatus("Error", "the option -d2 should be specified");
+ }
+ elsif(not -d $SPath2) {
+ exitStatus("Access_Error", "can't access directory \'".$SPath2."\'");
+ }
+ elsif(not -d $SPath2."/abi_dumps") {
+ exitStatus("Access_Error", "can't access directory \'".$SPath2."/abi_dumps\'");
+ }
+ # sys_dumps/<System>/<Arch>/...
+ my $SystemName1 = get_filename(get_dirname($SPath1));
+ my $SystemName2 = get_filename(get_dirname($SPath2));
+ # sys_dumps/<System>/<Arch>/...
+ my $ArchName = get_filename($SPath1);
+ if($ArchName ne get_filename($SPath2)) {
+ exitStatus("Error", "can't compare systems of different CPU architecture");
+ }
+ if(my $OStarget_Dump = readFile($SPath1."/target.txt"))
+ { # change target
+ $OStarget = $OStarget_Dump;
+ $LIB_EXT = getLIB_EXT($OStarget);
+ }
+ my $GroupByHeaders = 0;
+ if(my $Mode = readFile($SPath1."/mode.txt"))
+ { # change mode
+ if($Mode eq "headers-only")
+ { # -headers-only mode
+ $CheckHeadersOnly = 1;
+ $GroupByHeaders = 1;
+ }
+ if($Mode eq "group-by-headers") {
+ $GroupByHeaders = 1;
+ }
+ }
+ my $SYS_REPORT_PATH = "sys_compat_reports/".$SystemName1."_to_".$SystemName2."/$ArchName";
+ rmtree($SYS_REPORT_PATH);
+ my (%LibSoname1, %LibSoname2) = ();
+ foreach (split(/\n/, readFile($SPath1."/sonames.txt"))) {
+ if(my ($LFName, $Soname) = split(/;/, $_))
+ {
+ if($OStarget eq "symbian") {
+ $Soname=~s/\{.+\}//;
+ }
+ $LibSoname1{$LFName} = $Soname;
+ }
+ }
+ foreach (split(/\n/, readFile($SPath2."/sonames.txt"))) {
+ if(my ($LFName, $Soname) = split(/;/, $_))
+ {
+ if($OStarget eq "symbian") {
+ $Soname=~s/\{.+\}//;
+ }
+ $LibSoname2{$LFName} = $Soname;
+ }
+ }
+ my (%LibV1, %LibV2) = ();
+ foreach (split(/\n/, readFile($SPath1."/versions.txt"))) {
+ if(my ($LFName, $V) = split(/;/, $_)) {
+ $LibV1{$LFName} = $V;
+ }
+ }
+ foreach (split(/\n/, readFile($SPath2."/versions.txt"))) {
+ if(my ($LFName, $V) = split(/;/, $_)) {
+ $LibV2{$LFName} = $V;
+ }
+ }
+ my @Dumps1 = cmd_find($SPath1."/abi_dumps","f","*.tar.gz",1);
+ if(not @Dumps1)
+ { # zip-based dump
+ @Dumps1 = cmd_find($SPath1."/abi_dumps","f","*.zip",1);
+ }
+ my @Dumps2 = cmd_find($SPath2."/abi_dumps","f","*.tar.gz",1);
+ if(not @Dumps2)
+ { # zip-based dump
+ @Dumps2 = cmd_find($SPath2."/abi_dumps","f","*.zip",1);
+ }
+ my (%LibVers1, %LibVers2) = ();
+ foreach my $DPath (@Dumps1)
+ {
+ if(my $Name = isDump($DPath))
+ {
+ my ($Soname, $V) = ($LibSoname1{$Name}, $LibV1{$Name});
+ if(not $V) {
+ $V = parse_libname($Name, "version", $OStarget);
+ }
+ if($GroupByHeaders) {
+ $Soname = $Name;
+ }
+ $LibVers1{$Soname}{$V} = $DPath;
+ }
+ }
+ foreach my $DPath (@Dumps2)
+ {
+ if(my $Name = isDump($DPath))
+ {
+ my ($Soname, $V) = ($LibSoname2{$Name}, $LibV2{$Name});
+ if(not $V) {
+ $V = parse_libname($Name, "version", $OStarget);
+ }
+ if($GroupByHeaders) {
+ $Soname = $Name;
+ }
+ $LibVers2{$Soname}{$V} = $DPath;
+ }
+ }
+ my (%Added, %Removed) = ();
+ my (%ChangedSoname, %TestResults, %SONAME_Changed);
+ if(not $GroupByHeaders)
+ {
+ my %ChangedSoname_Safe = ();
+ foreach my $LName (sort keys(%LibSoname2))
+ { # libcurl.so.3 -> libcurl.so.4 (search for SONAME by the file name)
+ # OS #1 => OS #2
+ if(defined $LibVers2{$LName})
+ { # already registered
+ next;
+ }
+ my $Soname = $LibSoname2{$LName};
+ if(defined $LibVers2{$Soname}
+ and defined $LibVers1{$LName})
+ {
+ $LibVers2{$LName} = $LibVers2{$Soname};
+ $ChangedSoname_Safe{$Soname}=$LName;
+ }
+ }
+ foreach my $LName (sort keys(%LibSoname1))
+ { # libcurl.so.3 -> libcurl.so.4 (search for SONAME by the file name)
+ # OS #1 <= OS #2
+ if(defined $LibVers1{$LName})
+ { # already registered
+ next;
+ }
+ my $Soname = $LibSoname1{$LName};
+ if(defined $LibVers1{$Soname}
+ and defined $LibVers2{$LName}) {
+ $LibVers1{$LName} = $LibVers1{$Soname};
+ }
+ }
+ my (%AddedShort, %RemovedShort) = ();
+ if(not $GroupByHeaders) {
+ printMsg("INFO", "Checking added/removed libs");
+ }
+ foreach my $LName (sort {lc($a) cmp lc($b)} keys(%LibVers1))
+ { # removed libs
+ if(not is_target_lib($LName)) {
+ next;
+ }
+ if(not defined $LibVers1{$LName}) {
+ next;
+ }
+ my @Versions1 = keys(%{$LibVers1{$LName}});
+ if($#Versions1>=1)
+ { # should be only one version
+ next;
+ }
+ if(not defined $LibVers2{$LName}
+ or not keys(%{$LibVers2{$LName}}))
+ { # removed library
+ if(not $LibSoname2{$LName})
+ {
+ $RemovedShort{parse_libname($LName, "name+ext", $OStarget)}{$LName}=1;
+ $Removed{$LName}{"version"}=$Versions1[0];
+ my $ListPath = "info/$LName/symbols.html";
+ createSymbolsList($LibVers1{$LName}{$Versions1[0]},
+ $SYS_REPORT_PATH."/".$ListPath, $LName, $Versions1[0]."-".$SystemName1, $ArchName);
+ $Removed{$LName}{"list"} = $ListPath;
+ }
+ }
+ }
+ foreach my $LName (sort {lc($a) cmp lc($b)} keys(%LibVers2))
+ { # added libs
+ if(not is_target_lib($LName)) {
+ next;
+ }
+ if(not defined $LibVers2{$LName}) {
+ next;
+ }
+ my @Versions2 = keys(%{$LibVers2{$LName}});
+ if($#Versions2>=1)
+ { # should be only one version
+ next;
+ }
+ if($ChangedSoname_Safe{$LName})
+ { # changed soname but added the symbolic link for old-version library
+ next;
+ }
+ if(not defined $LibVers1{$LName}
+ or not keys(%{$LibVers1{$LName}}))
+ { # added library
+ if(not $LibSoname1{$LName})
+ {
+ $AddedShort{parse_libname($LName, "name+ext", $OStarget)}{$LName}=1;
+ $Added{$LName}{"version"}=$Versions2[0];
+ my $ListPath = "info/$LName/symbols.html";
+ createSymbolsList($LibVers2{$LName}{$Versions2[0]},
+ $SYS_REPORT_PATH."/".$ListPath, $LName, $Versions2[0]."-".$SystemName2, $ArchName);
+ $Added{$LName}{"list"} = $ListPath;
+ }
+ }
+ }
+ foreach my $LSName (keys(%AddedShort))
+ { # changed SONAME
+ my @AddedSonames = keys(%{$AddedShort{$LSName}});
+ next if(length(@AddedSonames)!=1);
+ my @RemovedSonames = keys(%{$RemovedShort{$LSName}});
+ next if(length(@RemovedSonames)!=1);
+ $ChangedSoname{$AddedSonames[0]}=$RemovedSonames[0];
+ $ChangedSoname{$RemovedSonames[0]}=$AddedSonames[0];
+ }
+ }
+ foreach my $LName (sort {lc($a) cmp lc($b)} keys(%LibVers1))
+ {
+ if(not is_target_lib($LName)) {
+ next;
+ }
+ my @Versions1 = keys(%{$LibVers1{$LName}});
+ if(not @Versions1 or $#Versions1>=1)
+ { # should be only one version
+ next;
+ }
+ my $LV1 = $Versions1[0];
+ my $DPath1 = $LibVers1{$LName}{$LV1};
+ my @Versions2 = keys(%{$LibVers2{$LName}});
+ if($#Versions2>=1)
+ { # should be only one version
+ next;
+ }
+ my ($LV2, $LName2, $DPath2) = ();
+ if(@Versions2)
+ {
+ $LV2 = $Versions2[0];
+ $DPath2 = $LibVers2{$LName}{$LV2};
+ }
+ elsif($LName2 = $ChangedSoname{$LName})
+ { # changed SONAME
+ @Versions2 = keys(%{$LibVers2{$LName2}});
+ if(not @Versions2 or $#Versions2>=1) {
+ next;
+ }
+ $LV2 = $Versions2[0];
+ $DPath2 = $LibVers2{$LName2}{$LV2};
+ $LName = parse_libname($LName, "name+ext", $OStarget);
+ $SONAME_Changed{$LName} = 1;
+ }
+ else
+ { # removed
+ next;
+ }
+ my ($FV1, $FV2) = ($LV1."-".$SystemName1, $LV2."-".$SystemName2);
+ my $ACC_compare = "perl $0 -l $LName -d1 \"$DPath1\" -d2 \"$DPath2\"";
+ my $LReportPath = "compat_reports/$LName/abi_compat_report.html";
+ my $LReportPath_Full = $SYS_REPORT_PATH."/".$LReportPath;
+ $ACC_compare .= " -report-path \"$LReportPath_Full\"";
+ if($CheckHeadersOnly) {
+ $ACC_compare .= " -headers-only";
+ }
+ if($GroupByHeaders) {
+ $ACC_compare .= " -component header";
+ }
+ if($Quiet)
+ { # quiet mode
+ $ACC_compare .= " -quiet";
+ }
+ if($LogMode eq "n") {
+ $ACC_compare .= " -logging-mode n";
+ }
+ elsif($Quiet) {
+ $ACC_compare .= " -logging-mode a";
+ }
+ if($Debug)
+ { # debug mode
+ $ACC_compare .= " -debug";
+ printMsg("INFO", "$ACC_compare");
+ }
+ printMsg("INFO_C", "Checking $LName: ");
+ system($ACC_compare." 1>$TMP_DIR/null 2>$TMP_DIR/$LName.stderr");
+ if(-s "$TMP_DIR/$LName.stderr")
+ {
+ my $ErrorLog = readFile("$TMP_DIR/$LName.stderr");
+ chomp($ErrorLog);
+ printMsg("INFO", "Failed ($ErrorLog)");
+ }
+ else
+ {
+ printMsg("INFO", "Ok");
+ $TestResults{$LName} = readAttributes($LReportPath_Full);
+ $TestResults{$LName}{"v1"} = $LV1;
+ $TestResults{$LName}{"v2"} = $LV2;
+ $TestResults{$LName}{"path"} = $LReportPath;
+ }
+ }
+ my $SONAME_Title = "SONAME";
+ if($OStarget eq "windows") {
+ $SONAME_Title = "DLL";
+ }
+ elsif($OStarget eq "symbian") {
+ $SONAME_Title = "DSO";
+ }
+ if($GroupByHeaders)
+ { # show the list of headers
+ $SONAME_Title = "Header File";
+ }
+ my $SYS_REPORT = "<h1>Binary compatibility between <span style='color:Blue;'>$SystemName1</span> and <span style='color:Blue;'>$SystemName2</span> on <span style='color:Blue;'>".showArch($ArchName)."</span></h1>\n";
+ # legend
+ $SYS_REPORT .= "<table>
+ <tr><td class='new' width='80px'>Added</td><td class='passed' width='80px'>Compatible</td></tr>
+ <tr><td class='warning'>Warning</td><td class='failed'>Incompatible</td></tr>
+ </table>";
+ $SYS_REPORT .= "<table class='wikitable'>
+ <tr><th rowspan='2'>$SONAME_Title<sup>".(keys(%TestResults) + keys(%Added) + keys(%Removed) - keys(%SONAME_Changed))."</sup></th>";
+ if(not $GroupByHeaders) {
+ $SYS_REPORT .= "<th colspan='2'>VERSION</th>";
+ }
+ $SYS_REPORT .= "<th rowspan='2'>Compatibility</th>
+ <th rowspan='2'>Added<br/>Symbols</th>
+ <th rowspan='2'>Removed<br/>Symbols</th>
+ <th colspan='3' style='white-space:nowrap;'>API Changes / Compatibility Problems</th></tr>";
+ if(not $GroupByHeaders) {
+ $SYS_REPORT .= "<tr><th>$SystemName1</th><th>$SystemName2</th>";
+ }
+ $SYS_REPORT .= "<th class='severity'>High</th><th class='severity'>Medium</th><th class='severity'>Low</th></tr>\n";
+ my %RegisteredPairs = ();
+ foreach my $LName (sort {lc($a) cmp lc($b)} (keys(%TestResults), keys(%Added), keys(%Removed)))
+ {
+ next if($SONAME_Changed{$LName});
+ my $CompatReport = $TestResults{$LName}{"path"};
+ my $Anchor = $LName;
+ $Anchor=~s/\+/p/g;# anchors to libFLAC++ is libFLACpp
+ $Anchor=~s/\~//g;# libqttracker.so.1~6
+ $SYS_REPORT .= "<tr>\n<td class='left'>$LName<a name=\'$Anchor\'></a></td>\n";
+ if(defined $Removed{$LName}) {
+ $SYS_REPORT .= "<td class='failed'>".$Removed{$LName}{"version"}."</td>\n";
+ }
+ elsif(defined $Added{$LName}) {
+ $SYS_REPORT .= "<td class='new'><a href='".$Added{$LName}{"list"}."'>added</a></td>\n";
+ }
+ elsif(not $GroupByHeaders) {
+ $SYS_REPORT .= "<td>".$TestResults{$LName}{"v1"}."</td>\n";
+ }
+ if(defined $Added{$LName})
+ { # added library
+ $SYS_REPORT .= "<td class='new'>".$Added{$LName}{"version"}."</td>\n";
+ $SYS_REPORT .= "<td class='passed'>100%</td>\n";
+ if($RegisteredPairs{$LName}) {
+ # do nothing
+ }
+ elsif(my $To = $ChangedSoname{$LName})
+ {
+ $RegisteredPairs{$To}=1;
+ $SYS_REPORT .= "<td colspan='5' rowspan='2'>SONAME has <a href='".$TestResults{parse_libname($LName, "name+ext", $OStarget)}{"path"}."'>changed</a></td>\n";
+ }
+ else {
+ foreach (1 .. 5) {
+ $SYS_REPORT .= "<td>n/a</td>\n"; # colspan='5'
+ }
+ }
+ $SYS_REPORT .= "</tr>\n";
+ next;
+ }
+ elsif(defined $Removed{$LName})
+ { # removed library
+ $SYS_REPORT .= "<td class='failed'><a href='".$Removed{$LName}{"list"}."'>removed</a></td>\n";
+ $SYS_REPORT .= "<td class='failed'>0%</td>\n";
+ if($RegisteredPairs{$LName}) {
+ # do nothing
+ }
+ elsif(my $To = $ChangedSoname{$LName})
+ {
+ $RegisteredPairs{$To}=1;
+ $SYS_REPORT .= "<td colspan='5' rowspan='2'>SONAME has <a href='".$TestResults{parse_libname($LName, "name+ext", $OStarget)}{"path"}."'>changed</a></td>\n";
+ }
+ else {
+ foreach (1 .. 5) {
+ $SYS_REPORT .= "<td>n/a</td>\n"; # colspan='5'
+ }
+ }
+ $SYS_REPORT .= "</tr>\n";
+ next;
+ }
+ elsif(not $GroupByHeaders) {
+ $SYS_REPORT .= "<td>".$TestResults{$LName}{"v2"}."</td>\n";
+ }
+ if($TestResults{$LName}{"verdict"} eq "compatible") {
+ $SYS_REPORT .= "<td class='passed'><a href=\'$CompatReport\'>100%</a></td>\n";
+ }
+ else
+ {
+ my $Compatible = 100 - $TestResults{$LName}{"affected"};
+ $SYS_REPORT .= "<td class='failed'><a href=\'$CompatReport\'>$Compatible%</a></td>\n";
+ }
+ my $AddedSym="";
+ if(my $Count = $TestResults{$LName}{"added"}) {
+ $AddedSym="<a href='$CompatReport\#Added'>$Count new</a>";
+ }
+ if($AddedSym) {
+ $SYS_REPORT.="<td class='new'>$AddedSym</td>";
+ }
+ else {
+ $SYS_REPORT.="<td class='passed'>0</td>";
+ }
+ my $RemovedSym="";
+ if(my $Count = $TestResults{$LName}{"removed"}) {
+ $RemovedSym="<a href='$CompatReport\#Removed'>$Count removed</a>";
+ }
+ if($RemovedSym) {
+ $SYS_REPORT.="<td class='failed'>$RemovedSym</td>";
+ }
+ else {
+ $SYS_REPORT.="<td class='passed'>0</td>";
+ }
+ my $High="";
+ if(my $Count = $TestResults{$LName}{"type_problems_high"}+$TestResults{$LName}{"interface_problems_high"}) {
+ $High="<a href='$CompatReport\#High_Risk_Problems'>".problem_title($Count)."</a>";
+ }
+ if($High) {
+ $SYS_REPORT.="<td class='failed'>$High</td>";
+ }
+ else {
+ $SYS_REPORT.="<td class='passed'>0</td>";
+ }
+ my $Medium="";
+ if(my $Count = $TestResults{$LName}{"type_problems_medium"}+$TestResults{$LName}{"interface_problems_medium"}) {
+ $Medium="<a href='$CompatReport\#Medium_Risk_Problems'>".problem_title($Count)."</a>";
+ }
+ if($Medium) {
+ $SYS_REPORT.="<td class='failed'>$Medium</td>";
+ }
+ else {
+ $SYS_REPORT.="<td class='passed'>0</td>";
+ }
+ my $Low="";
+ if(my $Count = $TestResults{$LName}{"type_problems_low"}+$TestResults{$LName}{"interface_problems_low"}+$TestResults{$LName}{"changed_constants"}) {
+ $Low="<a href='$CompatReport\#Low_Risk_Problems'>".warning_title($Count)."</a>";
+ }
+ if($Low) {
+ $SYS_REPORT.="<td class='warning'>$Low</td>";
+ }
+ else {
+ $SYS_REPORT.="<td class='passed'>0</td>";
+ }
+ $SYS_REPORT .= "</tr>\n";
+ }
+ my @META_DATA = ();
+ my %Stat = (
+ "total"=>int(keys(%TestResults)),
+ "added"=>int(keys(%Added)),
+ "removed"=>int(keys(%Removed))
+ );
+ foreach ("added", "removed")
+ {
+ my $Kind = $_."_interfaces";
+ foreach my $LName (keys(%TestResults)) {
+ $Stat{$Kind} += $TestResults{$LName}{$_};
+ }
+ push(@META_DATA, $Kind.":".$Stat{$Kind});
+ }
+ foreach my $T ("type", "interface")
+ {
+ foreach my $S ("high", "medium", "low")
+ {
+ my $Kind = $T."_problems_".$S;
+ foreach my $LName (keys(%TestResults)) {
+ $Stat{$Kind} += $TestResults{$LName}{$Kind};
+ }
+ push(@META_DATA, $Kind.":".$Stat{$Kind});
+ }
+ }
+ foreach my $LName (keys(%TestResults))
+ {
+ foreach ("affected", "changed_constants") {
+ $Stat{$_} += $TestResults{$LName}{$_};
+ }
+ if(not defined $Stat{"verdict"}
+ and $TestResults{$LName}{"verdict"} eq "incompatible") {
+ $Stat{"verdict"} = "incompatible";
+ }
+ }
+ if(not defined $Stat{"verdict"}) {
+ $Stat{"verdict"} = "compatible";
+ }
+ if($Stat{"total"}) {
+ $Stat{"affected"} /= $Stat{"total"};
+ }
+ else {
+ $Stat{"affected"} = 0;
+ }
+ $Stat{"affected"} = show_number($Stat{"affected"});
+ if($Stat{"verdict"}>1) {
+ $Stat{"verdict"} = 1;
+ }
+ push(@META_DATA, "changed_constants:".$Stat{"changed_constants"});
+ push(@META_DATA, "tool_version:".get_dumpversion("perl $0"));
+ foreach ("removed", "added", "total", "affected", "verdict") {
+ @META_DATA = ($_.":".$Stat{$_}, @META_DATA);
+ }
+
+ # bottom header
+ $SYS_REPORT .= "<tr><th rowspan='2'>$SONAME_Title</th>";
+ if(not $GroupByHeaders) {
+ $SYS_REPORT .= "<th>$SystemName1</th><th>$SystemName2</th>";
+ }
+ $SYS_REPORT .= "<th rowspan='2'>Compatibility</th>
+ <th rowspan='2'>Added<br/>Symbols</th>
+ <th rowspan='2'>Removed<br/>Symbols</th>
+ <th class='severity'>High</th><th class='severity'>Medium</th><th class='severity'>Low</th></tr>";
+ if(not $GroupByHeaders) {
+ $SYS_REPORT .= "<tr><th colspan='2'>VERSION</th>";
+ }
+ $SYS_REPORT .= "<th colspan='3' style='white-space:nowrap;'>API Changes / Compatibility Problems</th></tr>\n";
+ $SYS_REPORT .= "</table>";
+ my $Title = "$SystemName1 to $SystemName2 binary compatibility report";
+ my $Keywords = "compatibility, $SystemName1, $SystemName2, API, changes";
+ my $Description = "Binary compatibility between $SystemName1 and $SystemName2 on ".showArch($ArchName);
+ my $Styles = readStyles("CmpSystems.css");
+ writeFile($SYS_REPORT_PATH."/abi_compat_report.html", "<!-\- ".join(";", @META_DATA)." -\->\n".composeHTML_Head($Title, $Keywords, $Description, $Styles)."\n<body>
+ <div>$SYS_REPORT</div>
+ <br/><br/><br/><hr/>
+ ".getReportFooter($SystemName2)."
+ <div style='height:999px;'></div>\n</body></html>");
+ printMsg("INFO", "see detailed report:\n $SYS_REPORT_PATH/abi_compat_report.html");
+}
+
+sub readSystemDescriptor($)
+{
+ my $Content = $_[0];
+ $Content=~s/\/\*(.|\n)+?\*\///g;
+ $Content=~s/<\!--(.|\n)+?-->//g;
+ $SysDescriptor{"Name"} = parseTag(\$Content, "name");
+ my @Tools = ();
+ if(not $SysDescriptor{"Name"}) {
+ exitStatus("Error", "system name is not specified (<name> section)");
+ }
+ foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "libs")))
+ { # target libs
+ if(not -e $Path) {
+ exitStatus("Access_Error", "can't access \'$Path\'");
+ }
+ $Path = get_abs_path($Path);
+ $SysDescriptor{"Libs"}{clean_path($Path)} = 1;
+ }
+ foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs")))
+ { # target libs
+ if(not -d $Path) {
+ exitStatus("Access_Error", "can't access directory \'$Path\'");
+ }
+ $Path = get_abs_path($Path);
+ $SysDescriptor{"SearchLibs"}{clean_path($Path)} = 1;
+ }
+ foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "headers")))
+ {
+ if(not -e $Path) {
+ exitStatus("Access_Error", "can't access \'$Path\'");
+ }
+ $Path = get_abs_path($Path);
+ $SysDescriptor{"Headers"}{clean_path($Path)} = 1;
+ }
+ foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers")))
+ {
+ if(not -d $Path) {
+ exitStatus("Access_Error", "can't access directory \'$Path\'");
+ }
+ $Path = get_abs_path($Path);
+ $SysDescriptor{"SearchHeaders"}{clean_path($Path)} = 1;
+ }
+ foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools")))
+ {
+ if(not -d $Path) {
+ exitStatus("Access_Error", "can't access directory \'$Path\'");
+ }
+ $Path = get_abs_path($Path);
+ $Path = clean_path($Path);
+ $SysDescriptor{"Tools"}{$Path} = 1;
+ push(@Tools, $Path);
+ }
+ foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "gcc_options"))) {
+ $SysDescriptor{"GccOpts"}{clean_path($Path)} = 1;
+ }
+ if($SysDescriptor{"CrossPrefix"} = parseTag(\$Content, "cross_prefix"))
+ { # <cross_prefix> section of XML descriptor
+ $CrossPrefix = $SysDescriptor{"CrossPrefix"};
+ }
+ elsif($CrossPrefix)
+ { # -cross-prefix tool option
+ $SysDescriptor{"CrossPrefix"} = $CrossPrefix;
+ }
+ $SysDescriptor{"Defines"} = parseTag(\$Content, "defines");
+ if($SysDescriptor{"Image"} = parseTag(\$Content, "image"))
+ { # <image>
+ # FIXME: isn't implemented yet
+ if(not -f $SysDescriptor{"Image"}) {
+ exitStatus("Access_Error", "can't access \'".$SysDescriptor{"Image"}."\'");
+ }
+ }
+ return {"Tools"=>\@Tools,"CrossPrefix"=>$CrossPrefix};
+}
+
+sub readOpts($)
+{
+ my $S = $_[0];
+ $OStarget = $S->{"OStarget"};
+ $Debug = $S->{"Debug"};
+ $Quiet = $S->{"Quiet"};
+ $LogMode = $S->{"LogMode"};
+ $CheckHeadersOnly = $S->{"CheckHeadersOnly"};
+
+ $SystemRoot = $S->{"SystemRoot"};
+ $MODULES_DIR = $S->{"MODULES_DIR"};
+ $GCC_PATH = $S->{"GCC_PATH"};
+ $TargetSysInfo = $S->{"TargetSysInfo"};
+ $CrossPrefix = $S->{"CrossPrefix"};
+ $TargetLibraryName = $S->{"TargetLibraryName"};
+ $CrossGcc = $S->{"CrossGcc"};
+ $UseStaticLibs = $S->{"UseStaticLibs"};
+ $NoStdInc = $S->{"NoStdInc"};
+}
+
+sub check_list($$)
+{
+ my ($Item, $Skip) = @_;
+ return 0 if(not $Skip);
+ my @Patterns = @{$Skip};
+ foreach my $Pattern (@Patterns)
+ {
+ if($Pattern=~s/\*/.*/g)
+ { # wildcards
+ if($Item=~/$Pattern/) {
+ return 1;
+ }
+ }
+ elsif($Pattern=~/[\/\\]/)
+ { # directory
+ if($Item=~/\Q$Pattern\E/) {
+ return 1;
+ }
+ }
+ elsif($Item eq $Pattern
+ or get_filename($Item) eq $Pattern)
+ { # by name
+ return 1;
+ }
+ }
+ return 0;
+}
+
+sub filter_format($)
+{
+ my $FiltRef = $_[0];
+ foreach my $Entry (keys(%{$FiltRef}))
+ {
+ foreach my $Filt (@{$FiltRef->{$Entry}})
+ {
+ if($Filt=~/[\/\\]/) {
+ $Filt = path_format($Filt, $OSgroup);
+ }
+ }
+ }
+}
+
+sub read_sys_descriptor($)
+{
+ my $Path = $_[0];
+ my $Content = readFile($Path);
+ my %Tags = (
+ "headers" => "mf",
+ "skip_headers" => "mf",
+ "skip_libs" => "mf",
+ "include_preamble" => "mf",
+ "non_self_compiled" => "mf",
+ "add_include_paths" => "mf",
+ "gcc_options" => "m",
+ "skip_symbols" => "m",
+ "skip_types" => "m",
+ "ignore_symbols" => "h",
+ "defines" => "s"
+ );
+ my %DInfo = ();
+ foreach my $Tag (keys(%Tags))
+ {
+ if(my $TContent = parseTag(\$Content, $Tag))
+ {
+ if($Tags{$Tag}=~/m/)
+ { # multi-line (+order)
+ my @Items = split(/\s*\n\s*/, $TContent);
+ $DInfo{$Tag} = [];
+ foreach my $Item (@Items)
+ {
+ if($Tags{$Tag}=~/f/) {
+ $Item = path_format($Item, $OSgroup);
+ }
+ push(@{$DInfo{$Tag}}, $Item);
+ }
+
+ }
+ elsif($Tags{$Tag}=~/s/)
+ { # single element
+ $DInfo{$Tag} = $TContent;
+ }
+ else
+ { # hash array
+ my @Items = split(/\s*\n\s*/, $TContent);
+ foreach my $Item (@Items) {
+ $DInfo{$Tag}{$Item}=1;
+ }
+ }
+ }
+ }
+ return \%DInfo;
+}
+
+sub read_sys_info($)
+{
+ my $Target = $_[0];
+ my $SYS_INFO_PATH = $MODULES_DIR."/Targets";
+ if(-d $SYS_INFO_PATH."/".$Target)
+ { # symbian, windows
+ $SYS_INFO_PATH .= "/".$Target;
+ }
+ else
+ { # default
+ $SYS_INFO_PATH .= "/unix";
+ }
+ if($TargetSysInfo)
+ { # user-defined target
+ $SYS_INFO_PATH = $TargetSysInfo;
+ }
+ if(not -d $SYS_INFO_PATH) {
+ exitStatus("Module_Error", "can't access \'$SYS_INFO_PATH\'");
+ }
+ # Library Specific Info
+ my %SysInfo = ();
+ if(not -d $SYS_INFO_PATH."/descriptors/") {
+ exitStatus("Module_Error", "can't access \'$SYS_INFO_PATH/descriptors\'");
+ }
+ foreach my $DPath (cmd_find($SYS_INFO_PATH."/descriptors/","f","",1))
+ {
+ my $LSName = get_filename($DPath);
+ $LSName=~s/\.xml\Z//;
+ $SysInfo{$LSName} = read_sys_descriptor($DPath);
+ }
+ # Exceptions
+ if(check_gcc_version($GCC_PATH, "4.4"))
+ { # exception for libstdc++
+ $SysInfo{"libstdc++"}{"gcc_options"} = ["-std=c++0x"];
+ }
+ if($OStarget eq "symbian")
+ { # exception for libstdcpp
+ $SysInfo{"libstdcpp"}{"defines"} = "namespace std { struct nothrow_t {}; }";
+ }
+ if($SysDescriptor{"Name"}=~/maemo/i)
+ { # GL/gl.h: No such file
+ $SysInfo{"libSDL"}{"skip_headers"}=["SDL_opengl.h"];
+ }
+ if($OStarget eq "linux") {
+ $SysInfo{"libboost_"}{"headers"} = ["/boost/", "/asio/"];
+ }
+ # Common Info
+ if(not -f $SYS_INFO_PATH."/common.xml") {
+ exitStatus("Module_Error", "can't access \'$SYS_INFO_PATH/common.xml\'");
+ }
+ my $SysCInfo = read_sys_descriptor($SYS_INFO_PATH."/common.xml");
+ my @CompilerOpts = ();
+ if($SysDescriptor{"Name"}=~/maemo|meego/i) {
+ push(@CompilerOpts, "-DMAEMO_CHANGES", "-DM_APPLICATION_NAME=\\\"app\\\"");
+ }
+ if(my @Opts = keys(%{$SysDescriptor{"GccOpts"}})) {
+ push(@CompilerOpts, @Opts);
+ }
+ if(@CompilerOpts)
+ {
+ if(not $SysCInfo->{"gcc_options"}) {
+ $SysCInfo->{"gcc_options"} = [];
+ }
+ push(@{$SysCInfo->{"gcc_options"}}, @CompilerOpts);
+ }
+ foreach my $Name (keys(%SysInfo))
+ { # strict headers that should be
+ # matched for only one library
+ if($SysInfo{$Name}{"headers"}) {
+ $SysCInfo->{"sheaders"}{$Name} = $SysInfo{$Name}{"headers"};
+ }
+ }
+ return (\%SysInfo, $SysCInfo);
+}
+
+sub get_binversion($)
+{
+ my $Path = $_[0];
+ if($OStarget eq "windows"
+ and $LIB_EXT eq "dll")
+ { # get version of DLL using "sigcheck"
+ my $SigcheckCmd = get_CmdPath("sigcheck");
+ if(not $SigcheckCmd) {
+ return "";
+ }
+ my $VInfo = `$SigcheckCmd -n $Path 2>$TMP_DIR/null`;
+ $VInfo=~s/\s*\(.*\)\s*//;
+ chomp($VInfo);
+ return $VInfo;
+ }
+ return "";
+}
+
+sub get_soname($)
+{
+ my $Path = $_[0];
+ return if(not $Path or not -e $Path);
+ if(defined $Cache{"get_soname"}{$Path}) {
+ return $Cache{"get_soname"}{$Path};
+ }
+ my $ObjdumpCmd = get_CmdPath("objdump");
+ if(not $ObjdumpCmd) {
+ exitStatus("Not_Found", "can't find \"objdump\"");
+ }
+ my $SonameCmd = "$ObjdumpCmd -x $Path 2>$TMP_DIR/null";
+ if($OSgroup eq "windows") {
+ $SonameCmd .= " | find \"SONAME\"";
+ }
+ else {
+ $SonameCmd .= " | grep SONAME";
+ }
+ if(my $SonameInfo = `$SonameCmd`) {
+ if($SonameInfo=~/SONAME\s+([^\s]+)/) {
+ return ($Cache{"get_soname"}{$Path} = $1);
+ }
+ }
+ return ($Cache{"get_soname"}{$Path}="");
+}
+
+sub dumpSystem($)
+{ # -dump-system option handler
+ # should be used with -sysroot and -cross-gcc options
+ my $Opts = $_[0];
+ readOpts($Opts);
+ my $SYS_DUMP_PATH = "sys_dumps/".$SysDescriptor{"Name"}."/".getArch(1);
+ if(not $TargetLibraryName) {
+ rmtree($SYS_DUMP_PATH);
+ }
+ my (@SystemLibs, @SysHeaders) = ();
+ foreach my $Path (keys(%{$SysDescriptor{"Libs"}}))
+ {
+ if(not -e $Path) {
+ exitStatus("Access_Error", "can't access \'$Path\'");
+ }
+ if(-d $Path)
+ {
+ if(my @SubLibs = find_libs($Path,"",1)) {
+ push(@SystemLibs, @SubLibs);
+ }
+ $SysDescriptor{"SearchLibs"}{$Path}=1;
+ }
+ else
+ { # single file
+ push(@SystemLibs, $Path);
+ $SysDescriptor{"SearchLibs"}{get_dirname($Path)}=1;
+ }
+ }
+ foreach my $Path (keys(%{$SysDescriptor{"Headers"}}))
+ {
+ if(not -e $Path) {
+ exitStatus("Access_Error", "can't access \'$Path\'");
+ }
+ if(-d $Path)
+ {
+ if(my @SubHeaders = cmd_find($Path,"f","","")) {
+ push(@SysHeaders, @SubHeaders);
+ }
+ $SysDescriptor{"SearchHeaders"}{$Path}=1;
+ }
+ else
+ { # single file
+ push(@SysHeaders, $Path);
+ $SysDescriptor{"SearchHeaders"}{get_dirname($Path)}=1;
+ }
+ }
+ my $GroupByHeaders = 0;
+ if($CheckHeadersOnly)
+ { # -headers-only
+ $GroupByHeaders = 1;
+ # @SysHeaders = optimize_set(@SysHeaders);
+ }
+ elsif($SysDescriptor{"Image"})
+ { # one big image
+ $GroupByHeaders = 1;
+ @SystemLibs = ($SysDescriptor{"Image"});
+ }
+ writeFile($SYS_DUMP_PATH."/target.txt", $OStarget);
+ my (%SysLib_Symbols, %SymbolGroup, %Symbol_SysHeaders,
+ %SysHeader_Symbols, %SysLib_SysHeaders, %MatchByName) = ();
+ my (%Skipped, %Failed, %Success) = ();
+ my (%SysHeaderDir_SysLibs, %SysHeaderDir_SysHeaders) = ();
+ my (%LibPrefixes, %SymbolCounter, %TotalLibs) = ();
+ my %Glibc = map {$_=>1} (
+ "libc",
+ "libpthread"
+ );
+ my ($SysInfo, $SysCInfo) = read_sys_info($OStarget);
+ if(not $GroupByHeaders) {
+ printMsg("INFO", "Indexing sonames ...");
+ }
+ my (%LibSoname, %SysLibVersion) = ();
+ my %DevelPaths = map {$_=>1} @SystemLibs;
+ foreach my $Path (sort keys(%{$SysDescriptor{"SearchLibs"}})) {
+ foreach my $LPath (find_libs($Path,"",1)) {
+ $DevelPaths{$LPath}=1;
+ }
+ }
+ foreach my $LPath (keys(%DevelPaths))
+ { # register SONAMEs
+ my $LName = get_filename($LPath);
+ my $LRelPath = cut_path_prefix($LPath, $SystemRoot);
+ if(not is_target_lib($LName)) {
+ next;
+ }
+ if($OSgroup=~/\A(linux|macos|freebsd)\Z/
+ and $LName!~/\Alib/) {
+ next;
+ }
+ if(my $Soname = get_soname($LPath))
+ {
+ if($OStarget eq "symbian")
+ {
+ if($Soname=~/[\/\\]/)
+ { # L://epoc32/release/armv5/lib/gfxtrans{000a0000}.dso
+ $Soname = get_filename($Soname);
+ }
+ $Soname = lc($Soname);
+ }
+ if(not defined $LibSoname{$LName}) {
+ $LibSoname{$LName}=$Soname;
+ }
+ if(-l $LPath and my $Path = resolve_symlink($LPath))
+ {
+ my $Name = get_filename($Path);
+ if(not defined $LibSoname{$Name}) {
+ $LibSoname{$Name}=$Soname;
+ }
+ }
+ }
+ else
+ { # windows and others
+ $LibSoname{$LName}=$LName;
+ }
+ }
+ my $SONAMES = "";
+ foreach (sort {lc($a) cmp lc($b)} keys(%LibSoname)) {
+ $SONAMES .= $_.";".$LibSoname{$_}."\n";
+ }
+ if(not $GroupByHeaders) {
+ writeFile($SYS_DUMP_PATH."/sonames.txt", $SONAMES);
+ }
+ foreach my $LPath (sort keys(%DevelPaths))
+ {# register VERSIONs
+ my $LName = get_filename($LPath);
+ if(not is_target_lib($LName)
+ and not is_target_lib($LibSoname{$LName})) {
+ next;
+ }
+ if(my $V = get_binversion($LPath))
+ { # binary version
+ $SysLibVersion{$LName} = $V;
+ }
+ elsif(my $V = parse_libname($LName, "version", $OStarget))
+ { # source version
+ $SysLibVersion{$LName} = $V;
+ }
+ elsif($LName=~/([\d\.\-\_]+)\.$LIB_EXT\Z/)
+ { # libfreebl3.so
+ if($1 ne 32 and $1 ne 64) {
+ $SysLibVersion{$LName} = $1;
+ }
+ }
+ }
+ my $VERSIONS = "";
+ foreach (sort {lc($a) cmp lc($b)} keys(%SysLibVersion)) {
+ $VERSIONS .= $_.";".$SysLibVersion{$_}."\n";
+ }
+ if(not $GroupByHeaders) {
+ writeFile($SYS_DUMP_PATH."/versions.txt", $VERSIONS);
+ }
+ my %SysLibs = ();
+ foreach my $LPath (sort @SystemLibs)
+ {
+ my $LName = get_filename($LPath);
+ my $LSName = parse_libname($LName, "short", $OStarget);
+ my $LRelPath = cut_path_prefix($LPath, $SystemRoot);
+ if(not is_target_lib($LName)) {
+ next;
+ }
+ if($OSgroup=~/\A(linux|macos|freebsd)\Z/
+ and $LName!~/\Alib/) {
+ next;
+ }
+ if($OStarget eq "symbian")
+ {
+ if(my $V = parse_libname($LName, "version", $OStarget))
+ { # skip qtcore.dso
+ # register qtcore{00040604}.dso
+ delete($SysLibs{get_dirname($LPath)."\\".$LSName.".".$LIB_EXT});
+ my $MV = parse_libname($LibSoname{$LSName.".".$LIB_EXT}, "version", $OStarget);
+ if($MV and $V ne $MV)
+ { # skip other versions:
+ # qtcore{00040700}.dso
+ # qtcore{00040702}.dso
+ next;
+ }
+ }
+ }
+ if(my $Skip = $SysCInfo->{"skip_libs"})
+ { # do NOT check some libs
+ if(check_list($LRelPath, $Skip)) {
+ next;
+ }
+ }
+ if(-l $LPath)
+ { # symlinks
+ if(my $Path = resolve_symlink($LPath)) {
+ $SysLibs{$Path} = 1;
+ }
+ }
+ elsif(-f $LPath)
+ {
+ if($Glibc{$LSName}
+ and cmd_file($LPath)=~/ASCII/)
+ {# GNU ld scripts (libc.so, libpthread.so)
+ my @Candidates = cmd_find($SystemRoot."/lib","",$LSName.".".$LIB_EXT."*","1");
+ if(@Candidates)
+ {
+ my $Candidate = $Candidates[0];
+ if(-l $Candidate
+ and my $Path = resolve_symlink($Candidate)) {
+ $Candidate = $Path;
+ }
+ $SysLibs{$Candidate} = 1;
+ }
+ }
+ else {
+ $SysLibs{$LPath} = 1;
+ }
+ }
+ }
+ @SystemLibs = ();# clear memory
+ if(not $CheckHeadersOnly)
+ {
+ if($SysDescriptor{"Image"}) {
+ printMsg("INFO", "Reading symbols from image ...");
+ }
+ else {
+ printMsg("INFO", "Reading symbols from libraries ...");
+ }
+ }
+ foreach my $LPath (sort keys(%SysLibs))
+ {
+ my $LRelPath = cut_path_prefix($LPath, $SystemRoot);
+ my $LName = get_filename($LPath);
+ my $Library_Symbol = getSymbols_Lib(1, $LPath, 0, (), "-Weak");
+ my @AllSymbols = keys(%{$Library_Symbol->{$LName}});
+ my $tr_name = translateSymbols(@AllSymbols, 1);
+ foreach my $Symbol (@AllSymbols)
+ {
+ $Symbol=~s/[\@\$]+(.*)\Z//g;
+ if($Symbol=~/\A(_Z|\?)/)
+ {
+ if(skipGlobalData($Symbol)) {
+ next;
+ }
+ if($Symbol=~/(C1|C2|D0|D1|D2)E/)
+ { # do NOT analyze constructors
+ # and destructors
+ next;
+ }
+ my $Unmangled = $tr_name->{$Symbol};
+ $Unmangled=~s/<.+>//g;
+ if($Unmangled=~/\A([\w:]+)/)
+ { # cut out the parameters
+ my @Elems = split(/::/, $1);
+ my ($Class, $Short) = ();
+ $Short = $Elems[$#Elems];
+ if($#Elems>=1) {
+ $Class = $Elems[$#Elems-1];
+ pop(@Elems);
+ }
+ # the short and class name should be
+ # matched in one header file
+ $SymbolGroup{$LRelPath}{$Class} = $Short;
+ foreach my $Sym (@Elems)
+ {
+ if($SysCInfo->{"ignore_symbols"}{$Symbol})
+ { # do NOT match this symbol
+ next;
+ }
+ $SysLib_Symbols{$LPath}{$Sym}=1;
+ if(my $Prefix = getPrefix($Sym)) {
+ $LibPrefixes{$Prefix}{$LName}+=1;
+ }
+ $SymbolCounter{$Sym}{$LName}=1;
+ }
+ }
+ }
+ else
+ {
+ if($SysCInfo->{"ignore_symbols"}{$Symbol})
+ { # do NOT match this symbol
+ next;
+ }
+ $SysLib_Symbols{$LPath}{$Symbol}=1;
+ if(my $Prefix = getPrefix($Symbol)) {
+ $LibPrefixes{$Prefix}{$LName}+=1;
+ }
+ $SymbolCounter{$Symbol}{$LName}=1;
+ }
+ }
+ }
+ if(not $CheckHeadersOnly) {
+ writeFile($SYS_DUMP_PATH."/symbols.txt", Dumper(\%SysLib_Symbols));
+ }
+ my (%DupLibs, %VersionedLibs) = ();
+ foreach my $LPath1 (sort keys(%SysLib_Symbols))
+ { # match duplicated libs
+ # libmenu contains all symbols from libmenuw
+ my $SName = parse_libname(get_filename($LPath1), "shortest", $OStarget);
+ foreach my $LPath2 (sort keys(%SysLib_Symbols))
+ {
+ next if($LPath1 eq $LPath2);
+ if($SName eq parse_libname(get_filename($LPath2), "shortest", $OStarget))
+ { # libpython-X.Y
+ $VersionedLibs{$LPath1}{$LPath2}=1;
+ next;
+ }
+ my $Duplicate=1;
+ foreach (keys(%{$SysLib_Symbols{$LPath1}}))
+ {
+ if(not defined $SysLib_Symbols{$LPath2}{$_}) {
+ $Duplicate=0;
+ last;
+ }
+ }
+ if($Duplicate) {
+ $DupLibs{$LPath1}{$LPath2}=1;
+ }
+ }
+ }
+ foreach my $Prefix (keys(%LibPrefixes))
+ {
+ my @Libs = keys(%{$LibPrefixes{$Prefix}});
+ @Libs = sort {$LibPrefixes{$Prefix}{$b}<=>$LibPrefixes{$Prefix}{$a}} @Libs;
+ $LibPrefixes{$Prefix}=$Libs[0];
+ }
+ printMsg("INFO", "Reading symbols from headers ...");
+ foreach my $HPath (@SysHeaders)
+ {
+ $HPath = path_format($HPath, $OSgroup);
+ my $HRelPath = cut_path_prefix($HPath, $SystemRoot);
+ my ($HDir, $HName) = separate_path($HRelPath);
+ if(is_not_header($HName))
+ { # have a wrong extension: .gch, .in
+ next;
+ }
+ if($HName=~/~\Z/)
+ { # reserved copy
+ next;
+ }
+ if($HRelPath=~/[\/\\]_gen/)
+ { # telepathy-1.0/telepathy-glib/_gen
+ # telepathy-1.0/libtelepathy/_gen-tp-constants-deprecated.h
+ next;
+ }
+ if($HRelPath=~/include[\/\\]linux[\/\\]/)
+ { # kernel-space headers
+ next;
+ }
+ if($HRelPath=~/include[\/\\]asm[\/\\]/)
+ { # asm headers
+ next;
+ }
+ if($HRelPath=~/[\/\\]microb-engine[\/\\]/)
+ { # MicroB engine (Maemo 4)
+ next;
+ }
+ if($HRelPath=~/\Wprivate(\W|\Z)/)
+ { # private directories (include/tcl-private, ...)
+ next;
+ }
+ my $Content = readFile($HPath);
+ $Content=~s/\/\*(.|\n)+?\*\///g;
+ $Content=~s/\/\/.*?\n//g;# remove comments
+ $Content=~s/#\s*define[^\n\\]*(\\\n[^\n\\]*)+\n*//g;# remove defines
+ $Content=~s/#[^\n]*?\n//g;# remove directives
+ $Content=~s/(\A|\n)class\s+\w+;\n//g;# remove forward declarations
+ # FIXME: try to add preprocessing stage
+ foreach my $Symbol (split(/\W+/, $Content))
+ {
+ $Symbol_SysHeaders{$Symbol}{$HRelPath} = 1;
+ $SysHeader_Symbols{$HRelPath}{$Symbol} = 1;
+ }
+ $SysHeaderDir_SysHeaders{$HDir}{$HName} = 1;
+ my $HShort = $HName;
+ $HShort=~s/\.\w+\Z//g;
+ if($HShort=~/\Alib/) {
+ $MatchByName{$HShort} = $HRelPath;
+ }
+ elsif(get_filename(get_dirname($HRelPath))=~/\Alib(.+)\Z/)
+ { # libical/ical.h
+ if($HShort=~/\Q$1\E/) {
+ $MatchByName{"lib".$HShort} = $HRelPath;
+ }
+ }
+ elsif($OStarget eq "windows"
+ and $HShort=~/api\Z/) {
+ $MatchByName{$HShort} = $HRelPath;
+ }
+ }
+ my %SkipDHeaders = (
+ # header files, that should be in the <skip_headers> section
+ # but should be matched in the algorithm
+ # MeeGo 1.2 Harmattan
+ "libtelepathy-qt4" => ["TelepathyQt4/_gen", "client.h",
+ "TelepathyQt4/*-*", "debug.h", "global.h",
+ "properties.h", "Channel", "channel.h", "message.h"],
+ );
+ filter_format(\%SkipDHeaders);
+ if(not $GroupByHeaders) {
+ printMsg("INFO", "Matching symbols ...");
+ }
+ foreach my $LPath (sort keys(%SysLibs))
+ { # matching
+ my $LName = get_filename($LPath);
+ my $LNameSE = parse_libname($LName, "name+ext", $OStarget);
+ my $LRelPath = cut_path_prefix($LPath, $SystemRoot);
+ my $LSName = parse_libname($LName, "short", $OStarget);
+ my $SName = parse_libname($LName, "shortest", $OStarget);
+ if($LRelPath=~/\/debug\//)
+ { # debug libs
+ $Skipped{$LRelPath}=1;
+ next;
+ }
+ $TotalLibs{$LRelPath}=1;
+ $SysLib_SysHeaders{$LRelPath} = ();
+ if(keys(%{$SysLib_Symbols{$LPath}}))
+ { # try to match by name of the header
+ if(my $Path = $MatchByName{$LSName}) {
+ $SysLib_SysHeaders{$LRelPath}{$Path}="exact match ($LSName)";
+ }
+ if(length($SName)>=3
+ and my $Path = $MatchByName{"lib".$SName}) {
+ $SysLib_SysHeaders{$LRelPath}{$Path}="exact match (lib$SName)";
+ }
+ }
+ my (%SymbolDirs, %SymbolFiles) = ();
+ foreach my $Symbol (sort {length($b) cmp length($a)}
+ sort keys(%{$SysLib_Symbols{$LPath}}))
+ {
+ if($SysCInfo->{"ignore_symbols"}{$Symbol}) {
+ next;
+ }
+ if(not $DupLibs{$LPath}
+ and not $VersionedLibs{$LPath}
+ and keys(%{$SymbolCounter{$Symbol}})>=2
+ and my $Prefix = getPrefix($Symbol))
+ { # duplicated symbols
+ if($LibPrefixes{$Prefix}
+ and $LibPrefixes{$Prefix} ne $LName
+ and not $Glibc{$LSName}) {
+ next;
+ }
+ }
+ if(length($Symbol)<=2) {
+ next;
+ }
+ if($Symbol!~/[A-Z_0-9]/
+ and length($Symbol)<10
+ and keys(%{$Symbol_SysHeaders{$Symbol}})>=3)
+ { # undistinguished symbols
+ # FIXME: improve this filter
+ # signalfd (libc.so)
+ # regcomp (libpcreposix.so)
+ next;
+ }
+ if($Symbol=~/\A(_M_|_Rb_|_S_)/)
+ { # _M_insert, _Rb_tree, _S_destroy_c_locale
+ next;
+ }
+ if($Symbol=~/\A[A-Z][a-z]+\Z/)
+ { # Clone, Initialize, Skip, Unlock, Terminate, Chunk
+ next;
+ }
+ if($Symbol=~/\A[A-Z][A-Z]\Z/)
+ { # BC, PC, UP, SP
+ next;
+ }
+ if($Symbol=~/_t\Z/)
+ { # pthread_mutex_t, wchar_t
+ next;
+ }
+ my @SymHeaders = keys(%{$Symbol_SysHeaders{$Symbol}});
+ @SymHeaders = sort {lc($a) cmp lc($b)} @SymHeaders;# sort by name
+ @SymHeaders = sort {length(get_dirname($a))<=>length(get_dirname($b))} @SymHeaders;# sort by length
+ if(length($SName)>=3)
+ { # sort candidate headers by name
+ @SymHeaders = sort {$b=~/\Q$SName\E/i<=>$a=~/\Q$SName\E/i} @SymHeaders;
+ }
+ else
+ { # libz, libX11
+ @SymHeaders = sort {$b=~/lib\Q$SName\E/i<=>$a=~/lib\Q$SName\E/i} @SymHeaders;
+ @SymHeaders = sort {$b=~/\Q$SName\Elib/i<=>$a=~/\Q$SName\Elib/i} @SymHeaders;
+ }
+ @SymHeaders = sort {$b=~/\Q$LSName\E/i<=>$a=~/\Q$LSName\E/i} @SymHeaders;
+ @SymHeaders = sort {$SymbolDirs{get_dirname($b)}<=>$SymbolDirs{get_dirname($a)}} @SymHeaders;
+ @SymHeaders = sort {$SymbolFiles{get_filename($b)}<=>$SymbolFiles{get_filename($a)}} @SymHeaders;
+ foreach my $HRelPath (@SymHeaders)
+ {
+ if(my $Group = $SymbolGroup{$LRelPath}{$Symbol}) {
+ if(not $SysHeader_Symbols{$HRelPath}{$Group}) {
+ next;
+ }
+ }
+ if(my $Search = $SysInfo->{$LSName}{"headers"})
+ { # search for specified headers
+ if(not check_list($HRelPath, $Search)) {
+ next;
+ }
+ }
+ if(my $Skip = $SysInfo->{$LSName}{"skip_headers"})
+ { # do NOT search for some headers
+ if(check_list($HRelPath, $Skip)) {
+ next;
+ }
+ }
+ if(my $Skip = $SysCInfo->{"skip_headers"})
+ { # do NOT search for some headers
+ if(check_list($HRelPath, $Skip)) {
+ next;
+ }
+ }
+ if(my $Skip = $SysInfo->{$LSName}{"non_self_compiled"})
+ { # do NOT search for some headers
+ if(check_list($HRelPath, $Skip)) {
+ $SymbolDirs{get_dirname($HRelPath)}+=1;
+ $SymbolFiles{get_filename($HRelPath)}+=1;
+ next;
+ }
+ }
+ my $Continue = 1;
+ foreach my $Name (keys(%{$SysCInfo->{"sheaders"}}))
+ {
+ if($LSName!~/\Q$Name\E/
+ and check_list($HRelPath, $SysCInfo->{"sheaders"}{$Name}))
+ { # restriction to search for C++ or Boost headers
+ # in the boost/ and c++/ directories only
+ $Continue=0;
+ last;
+ }
+ }
+ if(not $Continue) {
+ next;
+ }
+ $SysLib_SysHeaders{$LRelPath}{$HRelPath}=$Symbol;
+ $SysHeaderDir_SysLibs{get_dirname($HRelPath)}{$LNameSE}=1;
+ $SysHeaderDir_SysLibs{get_dirname(get_dirname($HRelPath))}{$LNameSE}=1;
+ $SymbolDirs{get_dirname($HRelPath)}+=1;
+ $SymbolFiles{get_filename($HRelPath)}+=1;
+ last;# select one header for one symbol
+ }
+ }
+ if(keys(%{$SysLib_SysHeaders{$LRelPath}})) {
+ $Success{$LRelPath}=1;
+ }
+ else {
+ $Failed{$LRelPath}=1;
+ }
+ }
+ if(not $GroupByHeaders)
+ { # matching results
+ writeFile($SYS_DUMP_PATH."/match.txt", Dumper(\%SysLib_SysHeaders));
+ writeFile($SYS_DUMP_PATH."/skipped.txt", join("\n", sort keys(%Skipped)));
+ writeFile($SYS_DUMP_PATH."/failed.txt", join("\n", sort keys(%Failed)));
+ }
+ (%SysLib_Symbols, %SymbolGroup, %Symbol_SysHeaders, %SysHeader_Symbols) = ();# free memory
+ if($GroupByHeaders)
+ {
+ if($SysDescriptor{"Image"} and not $CheckHeadersOnly) {
+ @SysHeaders = keys(%{$SysLib_SysHeaders{$SysDescriptor{"Image"}}});
+ }
+ %SysLib_SysHeaders = ();
+ foreach my $Path (@SysHeaders)
+ {
+ if(my $Skip = $SysCInfo->{"skip_headers"})
+ { # do NOT search for some headers
+ if(check_list($Path, $Skip)) {
+ next;
+ }
+ }
+ $SysLib_SysHeaders{$Path}{$Path} = 1;
+ }
+ if($CheckHeadersOnly) {
+ writeFile($SYS_DUMP_PATH."/mode.txt", "headers-only");
+ }
+ else {
+ writeFile($SYS_DUMP_PATH."/mode.txt", "group-by-headers");
+ }
+ }
+ @SysHeaders = ();# clear memory
+ my (%Skipped, %Failed, %Success) = ();
+ printMsg("INFO", "Generating XML descriptors ...");
+ foreach my $LRelPath (keys(%SysLib_SysHeaders))
+ {
+ my $LName = get_filename($LRelPath);
+ my $DPath = $SYS_DUMP_PATH."/descriptors/$LName.xml";
+ unlink($DPath);
+ if(my @LibHeaders = keys(%{$SysLib_SysHeaders{$LRelPath}}))
+ {
+ my $LSName = parse_libname($LName, "short", $OStarget);
+ if($GroupByHeaders)
+ { # header short name
+ $LSName = $LName;
+ $LSName=~s/\.(.+?)\Z//;
+ }
+ my (%DirsHeaders, %Includes) = ();
+ foreach my $HRelPath (@LibHeaders) {
+ $DirsHeaders{get_dirname($HRelPath)}{$HRelPath}=1;
+ }
+ foreach my $Dir (keys(%DirsHeaders))
+ {
+ my $DirPart = 0;
+ my $TotalHeaders = keys(%{$SysHeaderDir_SysHeaders{$Dir}});
+ if($TotalHeaders) {
+ $DirPart = (keys(%{$DirsHeaders{$Dir}})*100)/$TotalHeaders;
+ }
+ my $Neighbourhoods = keys(%{$SysHeaderDir_SysLibs{$Dir}});
+ if($Neighbourhoods==1)
+ { # one lib in this directory
+ if(get_filename($Dir) ne "include"
+ and $DirPart>=5)
+ { # complete directory
+ $Includes{$Dir} = 1;
+ }
+ else
+ { # list of headers
+ @Includes{keys(%{$DirsHeaders{$Dir}})}=values(%{$DirsHeaders{$Dir}});
+ }
+ }
+ elsif((keys(%{$DirsHeaders{$Dir}})*100)/($#LibHeaders+1)>5)
+ {# remove 5% divergence
+ if(get_filename($Dir) ne "include"
+ and $DirPart>=50)
+ { # complete directory
+ $Includes{$Dir} = 1;
+ }
+ else
+ { # list of headers
+ @Includes{keys(%{$DirsHeaders{$Dir}})}=values(%{$DirsHeaders{$Dir}});
+ }
+ }
+ }
+ if($GroupByHeaders)
+ { # one header in one ABI dump
+ %Includes = ($LibHeaders[0] => 1);
+ }
+ my $LVersion = $SysLibVersion{$LName};
+ if($LVersion)
+ {# append by system name
+ $LVersion .= "-".$SysDescriptor{"Name"};
+ }
+ else {
+ $LVersion = $SysDescriptor{"Name"};
+ }
+ my @Content = ("<version>\n $LVersion\n</version>");
+ my @IncHeaders = sort {natural_sorting($a, $b)} keys(%Includes);
+ sort_by_word(\@IncHeaders, parse_libname($LName, "shortest", $OStarget));
+ if(is_abs($IncHeaders[0])) {
+ push(@Content, "<headers>\n ".join("\n ", @IncHeaders)."\n</headers>");
+ }
+ else {
+ push(@Content, "<headers>\n {RELPATH}/".join("\n {RELPATH}/", @IncHeaders)."\n</headers>");
+ }
+ if($GroupByHeaders)
+ {
+ if($SysDescriptor{"Image"}) {
+ push(@Content, "<libs>\n ".$SysDescriptor{"Image"}."\n</libs>");
+ }
+ }
+ else
+ {
+ if(is_abs($LRelPath) or -f $LRelPath) {
+ push(@Content, "<libs>\n $LRelPath\n</libs>");
+ }
+ else {
+ push(@Content, "<libs>\n {RELPATH}/$LRelPath\n</libs>");
+ }
+ }
+ if(my @SearchHeaders = keys(%{$SysDescriptor{"SearchHeaders"}})) {
+ push(@Content, "<search_headers>\n ".join("\n ", @SearchHeaders)."\n</search_headers>");
+ }
+ if(my @SearchLibs = keys(%{$SysDescriptor{"SearchLibs"}})) {
+ push(@Content, "<search_libs>\n ".join("\n ", @SearchLibs)."\n</search_libs>");
+ }
+ if(my @Tools = keys(%{$SysDescriptor{"Tools"}})) {
+ push(@Content, "<tools>\n ".join("\n ", @Tools)."\n</tools>");
+ }
+ my @Skip = ();
+ if($SysInfo->{$LSName}{"skip_headers"}) {
+ @Skip = (@Skip, @{$SysInfo->{$LSName}{"skip_headers"}});
+ }
+ if($SysCInfo->{"skip_headers"}) {
+ @Skip = (@Skip, @{$SysCInfo->{"skip_headers"}});
+ }
+ if($SysInfo->{$LSName}{"non_self_compiled"}) {
+ @Skip = (@Skip, @{$SysInfo->{$LSName}{"non_self_compiled"}});
+ }
+ if($SkipDHeaders{$LSName}) {
+ @Skip = (@Skip, @{$SkipDHeaders{$LSName}});
+ }
+ if(@Skip) {
+ push(@Content, "<skip_headers>\n ".join("\n ", @Skip)."\n</skip_headers>");
+ }
+ if($SysInfo->{$LSName}{"add_include_paths"}) {
+ push(@Content, "<add_include_paths>\n ".join("\n ", @{$SysInfo->{$LSName}{"add_include_paths"}})."\n</add_include_paths>");
+ }
+ if($SysInfo->{$LSName}{"skip_types"}) {
+ push(@Content, "<skip_types>\n ".join("\n ", @{$SysInfo->{$LSName}{"skip_types"}})."\n</skip_types>");
+ }
+ my @SkipSymb = ();
+ if($SysInfo->{$LSName}{"skip_symbols"}) {
+ push(@SkipSymb, @{$SysInfo->{$LSName}{"skip_symbols"}});
+ }
+ if($SysCInfo->{"skip_symbols"}) {
+ push(@SkipSymb, @{$SysCInfo->{"skip_symbols"}});
+ }
+ if(@SkipSymb) {
+ push(@Content, "<skip_symbols>\n ".join("\n ", @SkipSymb)."\n</skip_symbols>");
+ }
+ my @Preamble = ();
+ if($SysCInfo->{"include_preamble"}) {
+ push(@Preamble, @{$SysCInfo->{"include_preamble"}});
+ }
+ if($LSName=~/\AlibX\w+\Z/)
+ { # add Xlib.h for libXt, libXaw, libXext and others
+ push(@Preamble, "Xlib.h", "X11/Intrinsic.h");
+ }
+ if($SysInfo->{$LSName}{"include_preamble"}) {
+ push(@Preamble, @{$SysInfo->{$LSName}{"include_preamble"}});
+ }
+ if(@Preamble) {
+ push(@Content, "<include_preamble>\n ".join("\n ", @Preamble)."\n</include_preamble>");
+ }
+ my @Defines = ();
+ if($SysCInfo->{"defines"}) {
+ push(@Defines, $SysCInfo->{"defines"});
+ }
+ if($SysInfo->{$LSName}{"defines"}) {
+ push(@Defines, $SysInfo->{$LSName}{"defines"});
+ }
+ if($SysDescriptor{"Defines"}) {
+ push(@Defines, $SysDescriptor{"Defines"});
+ }
+ if(@Defines) {
+ push(@Content, "<defines>\n ".join("\n ", @Defines)."\n</defines>");
+ }
+ my @CompilerOpts = ();
+ if($SysCInfo->{"gcc_options"}) {
+ push(@CompilerOpts, @{$SysCInfo->{"gcc_options"}});
+ }
+ if($SysInfo->{$LSName}{"gcc_options"}) {
+ push(@CompilerOpts, @{$SysInfo->{$LSName}{"gcc_options"}});
+ }
+ if(@CompilerOpts) {
+ push(@Content, "<gcc_options>\n ".join("\n ", @CompilerOpts)."\n</gcc_options>");
+ }
+ if($SysDescriptor{"CrossPrefix"}) {
+ push(@Content, "<cross_prefix>\n ".$SysDescriptor{"CrossPrefix"}."\n</cross_prefix>");
+ }
+ writeFile($DPath, join("\n\n", @Content));
+ $Success{$LRelPath}=1;
+ }
+ }
+ printMsg("INFO", "Dumping ABIs:");
+ my %DumpSuccess = ();
+ my @Descriptors = cmd_find($SYS_DUMP_PATH."/descriptors","f","*.xml","1");
+ foreach my $DPath (sort {lc($a) cmp lc($b)} @Descriptors)
+ {
+ my $DName = get_filename($DPath);
+ my $LName = "";
+ if($DName=~/\A(.+).xml\Z/) {
+ $LName = $1;
+ }
+ else {
+ next;
+ }
+ if(not is_target_lib($LName)
+ and not is_target_lib($LibSoname{$LName})) {
+ next;
+ }
+ $DPath = cut_path_prefix($DPath, $ORIG_DIR);
+ my $ACC_dump = "perl $0";
+ if($GroupByHeaders)
+ { # header name is going here
+ $ACC_dump .= " -l $LName";
+ }
+ else {
+ $ACC_dump .= " -l ".parse_libname($LName, "name", $OStarget);
+ }
+ $ACC_dump .= " -dump \"$DPath\"";
+ if($SystemRoot)
+ {
+ $ACC_dump .= " -relpath \"$SystemRoot\"";
+ $ACC_dump .= " -sysroot \"$SystemRoot\"";
+ }
+ my $DumpPath = "$SYS_DUMP_PATH/abi_dumps/$LName.abi.".getAR_EXT($OSgroup);
+ $ACC_dump .= " -dump-path \"$DumpPath\"";
+ my $LogPath = "$SYS_DUMP_PATH/logs/$LName.txt";
+ unlink($LogPath);
+ $ACC_dump .= " -log-path \"$LogPath\"";
+ if($CrossGcc) {
+ $ACC_dump .= " -cross-gcc \"$CrossGcc\"";
+ }
+ if($CheckHeadersOnly) {
+ $ACC_dump .= " -headers-only";
+ }
+ if($UseStaticLibs) {
+ $ACC_dump .= " -static-libs";
+ }
+ if($GroupByHeaders) {
+ $ACC_dump .= " -header $LName";
+ }
+ if($NoStdInc
+ or $OStarget=~/windows|symbian/)
+ { # 1. user-defined
+ # 2. windows/minGW
+ # 3. symbian/GCC
+ $ACC_dump .= " -nostdinc";
+ }
+ if($Quiet)
+ { # quiet mode
+ $ACC_dump .= " -quiet";
+ }
+ if($LogMode eq "n") {
+ $ACC_dump .= " -logging-mode n";
+ }
+ elsif($Quiet) {
+ $ACC_dump .= " -logging-mode a";
+ }
+ if($Debug)
+ { # debug mode
+ $ACC_dump .= " -debug";
+ printMsg("INFO", "$ACC_dump");
+ }
+ printMsg("INFO_C", "Dumping $LName: ");
+ system($ACC_dump." 1>$TMP_DIR/null 2>$TMP_DIR/$LName.stderr");
+ appendFile("$SYS_DUMP_PATH/logs/$LName.txt", "The ACC parameters:\n $ACC_dump\n");
+ if(-s "$TMP_DIR/$LName.stderr")
+ {
+ appendFile("$SYS_DUMP_PATH/logs/$LName.txt", readFile("$TMP_DIR/$LName.stderr"));
+ if(get_CoreError($?>>8) eq "Invalid_Dump") {
+ printMsg("INFO", "Empty");
+ }
+ else {
+ printMsg("INFO", "Failed (\'$SYS_DUMP_PATH/logs/$LName.txt\')");
+ }
+ }
+ elsif(not -f $DumpPath) {
+ printMsg("INFO", "Failed (\'$SYS_DUMP_PATH/logs/$LName.txt\')");
+ }
+ else
+ {
+ $DumpSuccess{$LName}=1;
+ printMsg("INFO", "Ok");
+ }
+ }
+ if(not $GroupByHeaders)
+ { # general mode
+ printMsg("INFO", "Total libraries: ".keys(%TotalLibs));
+ printMsg("INFO", "Skipped libraries: ".keys(%Skipped)." ($SYS_DUMP_PATH/skipped.txt)");
+ printMsg("INFO", "Failed to find headers: ".keys(%Failed)." ($SYS_DUMP_PATH/failed.txt)");
+ }
+ printMsg("INFO", "Created descriptors: ".keys(%Success)." ($SYS_DUMP_PATH/descriptors/)");
+ printMsg("INFO", "Dumped ABIs: ".keys(%DumpSuccess)." ($SYS_DUMP_PATH/abi_dumps/)");
+ printMsg("INFO", "The ".$SysDescriptor{"Name"}." system ABI has been dumped to:\n $SYS_DUMP_PATH");
+}
+
+return 1; \ No newline at end of file
diff --git a/modules/Internals/RegTests.pm b/modules/Internals/RegTests.pm
new file mode 100644
index 0000000..20ff0aa
--- /dev/null
+++ b/modules/Internals/RegTests.pm
@@ -0,0 +1,3961 @@
+###########################################################################
+# Internal Regression Tests for ABI Compliance Checker
+#
+# Copyright (C) 2009-2010 The Linux Foundation.
+# Copyright (C) 2009-2011 Institute for System Programming, RAS.
+# Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+# Copyright (C) 2011 ROSA Laboratory.
+#
+# Written by Andrey Ponomarenko
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License or the GNU Lesser
+# General Public License as published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# and the GNU Lesser General Public License along with this program.
+# If not, see <http://www.gnu.org/licenses/>.
+###########################################################################
+use strict;
+
+my ($TestDump, $Debug, $Quiet, $ExtendedCheck,
+$LogMode, $ReportFormat, $LIB_EXT, $GCC_PATH);
+my $OSgroup = get_OSgroup();
+
+sub testTool($$$$$$$$)
+{
+ ($TestDump, $Debug, $Quiet, $ExtendedCheck,
+ $LogMode, $ReportFormat, $LIB_EXT, $GCC_PATH) = @_;
+ testC();
+ testCpp();
+}
+
+sub testCpp()
+{
+ printMsg("INFO", "verifying detectable C++ library changes");
+ my ($HEADER1, $SOURCE1, $HEADER2, $SOURCE2) = ();
+ my $DECL_SPEC = ($OSgroup eq "windows")?"__declspec( dllexport )":"";
+ my $EXTERN = ($OSgroup eq "windows")?"extern ":"";# add "extern" for CL compiler
+
+ # Begin namespace
+ $HEADER1 .= "namespace TestNS {\n";
+ $HEADER2 .= "namespace TestNS {\n";
+ $SOURCE1 .= "namespace TestNS {\n";
+ $SOURCE2 .= "namespace TestNS {\n";
+
+ # Global_Data_Became_Const
+ $HEADER1 .= "
+ class $DECL_SPEC DataBecameConst {
+ public:
+ static int data;
+ };";
+ $SOURCE1 .= "
+ int DataBecameConst::data = 10;";
+
+ $HEADER2 .= "
+ class $DECL_SPEC DataBecameConst {
+ public:
+ static const int data;
+ };";
+ $SOURCE2 .= "
+ const int DataBecameConst::data = 10;";
+
+ # Global_Data_Became_Non_Const
+ $HEADER1 .= "
+ class $DECL_SPEC DataBecameNonConst {
+ public:
+ static const int data;
+ };";
+ $SOURCE1 .= "
+ const int DataBecameNonConst::data = 10;";
+
+ $HEADER2 .= "
+ class $DECL_SPEC DataBecameNonConst {
+ public:
+ static int data;
+ };";
+ $SOURCE2 .= "
+ int DataBecameNonConst::data = 10;";
+
+ # Parameter_Became_Restrict
+ $HEADER1 .= "
+ class $DECL_SPEC ParameterBecameRestrict {
+ public:
+ int method(int* param);
+ };";
+ $SOURCE1 .= "
+ int ParameterBecameRestrict::method(int* param) { return 0; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC ParameterBecameRestrict {
+ public:
+ int method(int* __restrict param);
+ };";
+ $SOURCE2 .= "
+ int ParameterBecameRestrict::method(int* __restrict param) { return 0; }";
+
+ # Field_Became_Volatile
+ $HEADER1 .= "
+ class $DECL_SPEC FieldBecameVolatile {
+ public:
+ int method(int param);
+ int f;
+ };";
+ $SOURCE1 .= "
+ int FieldBecameVolatile::method(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC FieldBecameVolatile {
+ public:
+ int method(int param);
+ volatile int f;
+ };";
+ $SOURCE2 .= "
+ int FieldBecameVolatile::method(int param) { return param; }";
+
+ # Method_Became_Const_Volatile
+ $HEADER1 .= "
+ class $DECL_SPEC MethodBecameConstVolatile {
+ public:
+ int method(int param);
+ };";
+ $SOURCE1 .= "
+ int MethodBecameConstVolatile::method(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC MethodBecameConstVolatile {
+ public:
+ int method(int param) volatile const;
+ };";
+ $SOURCE2 .= "
+ int MethodBecameConstVolatile::method(int param) volatile const { return param; }";
+
+ # Method_Became_Const
+ $HEADER1 .= "
+ class $DECL_SPEC MethodBecameConst {
+ public:
+ int method(int param);
+ };";
+ $SOURCE1 .= "
+ int MethodBecameConst::method(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC MethodBecameConst {
+ public:
+ int method(int param) const;
+ };";
+ $SOURCE2 .= "
+ int MethodBecameConst::method(int param) const { return param; }";
+
+ # Method_Became_Volatile
+ $HEADER1 .= "
+ class $DECL_SPEC MethodBecameVolatile {
+ public:
+ int method(int param);
+ };";
+ $SOURCE1 .= "
+ int MethodBecameVolatile::method(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC MethodBecameVolatile {
+ public:
+ int method(int param) volatile;
+ };";
+ $SOURCE2 .= "
+ int MethodBecameVolatile::method(int param) volatile { return param; }";
+
+ # Virtual_Method_Position (multiple bases)
+ $HEADER1 .= "
+ class $DECL_SPEC PrimaryBase
+ {
+ public:
+ virtual ~PrimaryBase();
+ virtual void foo();
+ };
+ class $DECL_SPEC SecondaryBase
+ {
+ public:
+ virtual ~SecondaryBase();
+ virtual void bar();
+ };
+ class UnsafeVirtualOverride: public PrimaryBase, public SecondaryBase
+ {
+ public:
+ UnsafeVirtualOverride();
+ ~UnsafeVirtualOverride();
+ void foo();
+ };";
+ $SOURCE1 .= "
+ PrimaryBase::~PrimaryBase() { }
+ void PrimaryBase::foo() { }
+
+ SecondaryBase::~SecondaryBase() { }
+ void SecondaryBase::bar() { }
+
+ UnsafeVirtualOverride::UnsafeVirtualOverride() { }
+ UnsafeVirtualOverride::~UnsafeVirtualOverride() { }
+ void UnsafeVirtualOverride::foo() { }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC PrimaryBase
+ {
+ public:
+ virtual ~PrimaryBase();
+ virtual void foo();
+ };
+ class $DECL_SPEC SecondaryBase
+ {
+ public:
+ virtual ~SecondaryBase();
+ virtual void bar();
+ };
+ class UnsafeVirtualOverride: public PrimaryBase, public SecondaryBase
+ {
+ public:
+ UnsafeVirtualOverride();
+ ~UnsafeVirtualOverride();
+ void foo();
+ void bar();
+ };";
+ $SOURCE2 .= "
+ PrimaryBase::~PrimaryBase() { }
+ void PrimaryBase::foo() { }
+
+ SecondaryBase::~SecondaryBase() { }
+ void SecondaryBase::bar() { }
+
+ UnsafeVirtualOverride::UnsafeVirtualOverride() { }
+ UnsafeVirtualOverride::~UnsafeVirtualOverride() { }
+ void UnsafeVirtualOverride::foo() { }
+ void UnsafeVirtualOverride::bar() { }";
+
+ # Removed_Interface (inline virtual d-tor)
+ $HEADER1 .= "
+ template <typename T>
+ class $DECL_SPEC BaseTemplate {
+ public:
+ BaseTemplate() { }
+ virtual int method(int param) { return param; };
+ virtual ~BaseTemplate() { };
+ };
+ class $DECL_SPEC RemovedVirtualDestructor: public BaseTemplate<int> {
+ public:
+ RemovedVirtualDestructor() { };
+ virtual int method2(int param);
+ };";
+ $SOURCE1 .= "
+ int RemovedVirtualDestructor::method2(int param) { return param; }";
+
+ $HEADER2 .= "
+ template <typename T>
+ class $DECL_SPEC BaseTemplate {
+ public:
+ BaseTemplate() { }
+ virtual int method(int param) { return param; };
+ //virtual ~BaseTemplate() { };
+ };
+ class $DECL_SPEC RemovedVirtualDestructor: public BaseTemplate<int> {
+ public:
+ RemovedVirtualDestructor() { };
+ virtual int method2(int param);
+ };";
+ $SOURCE2 .= "
+ int RemovedVirtualDestructor::method2(int param) { return param; }";
+
+ # Added_Virtual_Method_At_End
+ $HEADER1 .= "
+ class $DECL_SPEC DefaultConstructor {
+ public:
+ DefaultConstructor() { }
+ virtual int method(int param);
+ };";
+ $SOURCE1 .= "
+ int DefaultConstructor::method(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC DefaultConstructor {
+ public:
+ DefaultConstructor() { }
+ virtual int method(int param);
+ virtual int addedMethod(int param);
+ };";
+ $SOURCE2 .= "
+ int DefaultConstructor::method(int param) { return addedMethod(param); }
+ int DefaultConstructor::addedMethod(int param) { return param; }";
+
+ # Added_Enum_Member
+ $HEADER1 .= "
+ enum AddedEnumMember {
+ OldMember
+ };
+ $DECL_SPEC int addedEnumMember(enum AddedEnumMember param);";
+ $SOURCE1 .= "
+ int addedEnumMember(enum AddedEnumMember param) { return 0; }";
+
+ $HEADER2 .= "
+ enum AddedEnumMember {
+ OldMember,
+ NewMember
+ };
+ $DECL_SPEC int addedEnumMember(enum AddedEnumMember param);";
+ $SOURCE2 .= "
+ int addedEnumMember(enum AddedEnumMember param) { return 0; }";
+
+ # Parameter_Type_Format (Safe)
+ $HEADER1 .= "
+ struct DType
+ {
+ int i;
+ double j;
+ };
+ $DECL_SPEC int parameterTypeFormat(struct DType param);";
+ $SOURCE1 .= "
+ int parameterTypeFormat(struct DType param) { return 0; }";
+
+ $HEADER2 .= "
+ class DType
+ {
+ int i;
+ double j;
+ };
+ $DECL_SPEC int parameterTypeFormat(class DType param);";
+ $SOURCE2 .= "
+ int parameterTypeFormat(class DType param) { return 0; }";
+
+ # Removed_Virtual_Method (inline)
+ $HEADER1 .= "
+ class $DECL_SPEC RemovedInlineVirtualFunction {
+ public:
+ RemovedInlineVirtualFunction();
+ virtual int removedMethod(int param) { return 0; }
+ virtual int method(int param);
+ };";
+ $SOURCE1 .= "
+ int RemovedInlineVirtualFunction::method(int param) { return param; }
+ RemovedInlineVirtualFunction::RemovedInlineVirtualFunction() { }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC RemovedInlineVirtualFunction {
+ public:
+ RemovedInlineVirtualFunction();
+ virtual int method(int param);
+ };";
+ $SOURCE2 .= "
+ int RemovedInlineVirtualFunction::method(int param) { return param; }
+ RemovedInlineVirtualFunction::RemovedInlineVirtualFunction() { }";
+
+ # MethodPtr
+ $HEADER1 .= "
+ class TestMethodPtr {
+ public:
+ typedef void (TestMethodPtr::*Method)(int*);
+ Method _method;
+ TestMethodPtr();
+ void method();
+ };";
+ $SOURCE1 .= "
+ TestMethodPtr::TestMethodPtr() { }
+ void TestMethodPtr::method() { }";
+
+ $HEADER2 .= "
+ class TestMethodPtr {
+ public:
+ typedef void (TestMethodPtr::*Method)(int*, void*);
+ Method _method;
+ TestMethodPtr();
+ void method();
+ };";
+ $SOURCE2 .= "
+ TestMethodPtr::TestMethodPtr() { }
+ void TestMethodPtr::method() { }";
+
+ # FieldPtr
+ $HEADER1 .= "
+ class TestFieldPtr {
+ public:
+ typedef void* (TestFieldPtr::*Field);
+ Field _field;
+ TestFieldPtr();
+ void method(void*);
+ };";
+ $SOURCE1 .= "
+ TestFieldPtr::TestFieldPtr(){ }
+ void TestFieldPtr::method(void*) { }";
+
+ $HEADER2 .= "
+ class TestFieldPtr {
+ public:
+ typedef int (TestFieldPtr::*Field);
+ Field _field;
+ TestFieldPtr();
+ void method(void*);
+ };";
+ $SOURCE2 .= "
+ TestFieldPtr::TestFieldPtr(){ }
+ void TestFieldPtr::method(void*) { }";
+
+ # Removed_Symbol (Template Specializations)
+ $HEADER1 .= "
+ template <unsigned int _TP, typename AAA>
+ class Template {
+ public:
+ char const *field;
+ };
+ template <unsigned int _TP, typename AAA>
+ class TestRemovedTemplate {
+ public:
+ char const *field;
+ void method(int);
+ };
+ template <>
+ class TestRemovedTemplate<7, char> {
+ public:
+ char const *field;
+ void method(int);
+ };";
+ $SOURCE1 .= "
+ void TestRemovedTemplate<7, char>::method(int){ }";
+
+ # Removed_Symbol (Template Specializations)
+ $HEADER1 .= "
+ template <typename TName>
+ int removedTemplateSpec(TName);
+
+ template <> int removedTemplateSpec<char>(char);";
+ $SOURCE1 .= "
+ template <> int removedTemplateSpec<char>(char){return 0;}";
+
+ # Global_Data_Value (int)
+ $HEADER1 .= "
+ $EXTERN $DECL_SPEC const int globalDataValue = 10;";
+
+ $HEADER2 .= "
+ $EXTERN $DECL_SPEC const int globalDataValue = 15;";
+
+ # Global_Data_Became_Non_Const (int)
+ $HEADER1 .= "
+ $EXTERN $DECL_SPEC const int globalDataBecameNonConst = 10;";
+
+ $HEADER2 .= "
+ extern $DECL_SPEC int globalDataBecameNonConst;";
+ $SOURCE2 .= "
+ int globalDataBecameNonConst = 15;";
+
+ # Global_Data_Became_Const (safe)
+ $HEADER1 .= "
+ extern $DECL_SPEC int globalDataBecameConst;";
+ $SOURCE1 .= "
+ int globalDataBecameConst = 10;";
+
+ $HEADER2 .= "
+ $EXTERN $DECL_SPEC const int globalDataBecameConst=15;";
+
+ # Removed_Field (Ref)
+ $HEADER1 .= "
+ struct TestRefChange {
+ int a, b, c;
+ };
+ $DECL_SPEC int paramRefChange(const TestRefChange & p1, int p2);";
+ $SOURCE1 .= "
+ int paramRefChange(const TestRefChange & p1, int p2) { return p2; }";
+
+ $HEADER2 .= "
+ struct TestRefChange {
+ int a, b;
+ };
+ $DECL_SPEC int paramRefChange(const TestRefChange & p1, int p2);";
+ $SOURCE2 .= "
+ int paramRefChange(const TestRefChange & p1, int p2) { return p2; }";
+
+ # Removed_Parameter
+ $HEADER1 .= "
+ $DECL_SPEC int removedParameter(int param, int removed_param);";
+ $SOURCE1 .= "
+ int removedParameter(int param, int removed_param) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int removedParameter(int param);";
+ $SOURCE2 .= "
+ int removedParameter(int param) { return 0; }";
+
+ # Added_Parameter
+ $HEADER1 .= "
+ $DECL_SPEC int addedParameter(int param);";
+ $SOURCE1 .= "
+ int addedParameter(int param) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int addedParameter(int param, int added_param);";
+ $SOURCE2 .= "
+ int addedParameter(int param, int added_param) { return 0; }";
+
+ # Added
+ $HEADER2 .= "
+ typedef int (*FUNCPTR_TYPE)(int a, int b);
+ $DECL_SPEC int addedFunc(FUNCPTR_TYPE*const** f);";
+ $SOURCE2 .= "
+ int addedFunc(FUNCPTR_TYPE*const** f) { return 0; }";
+
+ # Added_Virtual_Method
+ $HEADER1 .= "
+ class $DECL_SPEC AddedVirtualMethod {
+ public:
+ virtual int method(int param);
+ };";
+ $SOURCE1 .= "
+ int AddedVirtualMethod::method(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC AddedVirtualMethod {
+ public:
+ virtual int addedMethod(int param);
+ virtual int method(int param);
+ };";
+ $SOURCE2 .= "
+ int AddedVirtualMethod::addedMethod(int param) {
+ return param;
+ }
+ int AddedVirtualMethod::method(int param) { return param; }";
+
+ # Added_Virtual_Method (added "virtual" attribute)
+ $HEADER1 .= "
+ class $DECL_SPEC BecameVirtualMethod {
+ public:
+ int becameVirtual(int param);
+ virtual int method(int param);
+ };";
+ $SOURCE1 .= "
+ int BecameVirtualMethod::becameVirtual(int param) { return param; }
+ int BecameVirtualMethod::method(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC BecameVirtualMethod {
+ public:
+ virtual int becameVirtual(int param);
+ virtual int method(int param);
+ };";
+ $SOURCE2 .= "
+ int BecameVirtualMethod::becameVirtual(int param) { return param; }
+ int BecameVirtualMethod::method(int param) { return param; }";
+
+ # Added_Pure_Virtual_Method
+ $HEADER1 .= "
+ class $DECL_SPEC AddedPureVirtualMethod {
+ public:
+ virtual int method(int param);
+ int otherMethod(int param);
+ };";
+ $SOURCE1 .= "
+ int AddedPureVirtualMethod::method(int param) { return param; }
+ int AddedPureVirtualMethod::otherMethod(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC AddedPureVirtualMethod {
+ public:
+ virtual int addedMethod(int param)=0;
+ virtual int method(int param);
+ int otherMethod(int param);
+ };";
+ $SOURCE2 .= "
+ int AddedPureVirtualMethod::method(int param) { return param; }
+ int AddedPureVirtualMethod::otherMethod(int param) { return param; }";
+
+ # Added_Virtual_Method_At_End (Safe)
+ $HEADER1 .= "
+ class $DECL_SPEC AddedVirtualMethodAtEnd {
+ public:
+ AddedVirtualMethodAtEnd();
+ int method1(int param);
+ virtual int method2(int param);
+ };";
+ $SOURCE1 .= "
+ AddedVirtualMethodAtEnd::AddedVirtualMethodAtEnd() { }
+ int AddedVirtualMethodAtEnd::method1(int param) { return param; }
+ int AddedVirtualMethodAtEnd::method2(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC AddedVirtualMethodAtEnd {
+ public:
+ AddedVirtualMethodAtEnd();
+ int method1(int param);
+ virtual int method2(int param);
+ virtual int addedMethod(int param);
+ };";
+ $SOURCE2 .= "
+ AddedVirtualMethodAtEnd::AddedVirtualMethodAtEnd() { }
+ int AddedVirtualMethodAtEnd::method1(int param) { return param; }
+ int AddedVirtualMethodAtEnd::method2(int param) { return param; }
+ int AddedVirtualMethodAtEnd::addedMethod(int param) { return param; }";
+
+ # Added_Virtual_Method_At_End (With Default Constructor)
+ $HEADER1 .= "
+ class $DECL_SPEC AddedVirtualMethodAtEnd_DefaultConstructor {
+ public:
+ int method1(int param);
+ virtual int method2(int param);
+ };";
+ $SOURCE1 .= "
+ int AddedVirtualMethodAtEnd_DefaultConstructor::method1(int param) { return param; }
+ int AddedVirtualMethodAtEnd_DefaultConstructor::method2(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC AddedVirtualMethodAtEnd_DefaultConstructor {
+ public:
+ int method1(int param);
+ virtual int method2(int param);
+ virtual int addedMethod(int param);
+ };";
+ $SOURCE2 .= "
+ int AddedVirtualMethodAtEnd_DefaultConstructor::method1(int param) { return param; }
+ int AddedVirtualMethodAtEnd_DefaultConstructor::method2(int param) { return param; }
+ int AddedVirtualMethodAtEnd_DefaultConstructor::addedMethod(int param) { return param; }";
+
+ # Added_First_Virtual_Method
+ $HEADER1 .= "
+ class $DECL_SPEC AddedFirstVirtualMethod {
+ public:
+ int method(int param);
+ };";
+ $SOURCE1 .= "
+ int AddedFirstVirtualMethod::method(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC AddedFirstVirtualMethod {
+ public:
+ int method(int param);
+ virtual int addedMethod(int param);
+ };";
+ $SOURCE2 .= "
+ int AddedFirstVirtualMethod::method(int param) { return param; }
+ int AddedFirstVirtualMethod::addedMethod(int param) { return param; }";
+
+ # Removed_Virtual_Method
+ $HEADER1 .= "
+ class $DECL_SPEC RemovedVirtualFunction {
+ public:
+ virtual int removedMethod(int param);
+ virtual int vMethod(int param);
+ };";
+ $SOURCE1 .= "
+ int RemovedVirtualFunction::removedMethod(int param) { return param; }
+ int RemovedVirtualFunction::vMethod(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC RemovedVirtualFunction {
+ public:
+ int removedMethod(int param);
+ virtual int vMethod(int param);
+ };";
+ $SOURCE2 .= "
+ int RemovedVirtualFunction::removedMethod(int param) { return param; }
+ int RemovedVirtualFunction::vMethod(int param) { return param; }";
+
+ # Removed_Virtual_Method (Pure, From the End)
+ $HEADER1 .= "
+ class $DECL_SPEC RemovedPureVirtualMethodFromEnd {
+ public:
+ virtual int method(int param);
+ virtual int removedMethod(int param)=0;
+ };";
+ $SOURCE1 .= "
+ int RemovedPureVirtualMethodFromEnd::method(int param) { return param; }
+ int RemovedPureVirtualMethodFromEnd::removedMethod(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC RemovedPureVirtualMethodFromEnd
+ {
+ public:
+ virtual int method(int param);
+ int removedMethod(int param);
+ };";
+ $SOURCE2 .= "
+ int RemovedPureVirtualMethodFromEnd::method(int param) { return param; }
+ int RemovedPureVirtualMethodFromEnd::removedMethod(int param) { return param; }";
+
+ # Removed_Symbol (Pure with Implementation)
+ $HEADER1 .= "
+ class $DECL_SPEC RemovedPureSymbol {
+ public:
+ virtual int method(int param);
+ virtual int removedMethod(int param)=0;
+ };";
+ $SOURCE1 .= "
+ int RemovedPureSymbol::method(int param) { return param; }
+ int RemovedPureSymbol::removedMethod(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC RemovedPureSymbol
+ {
+ public:
+ virtual int method(int param);
+ };";
+ $SOURCE2 .= "
+ int RemovedPureSymbol::method(int param) { return param; }";
+
+ # Removed_Virtual_Method (From the End)
+ $HEADER1 .= "
+ class $DECL_SPEC RemovedVirtualMethodFromEnd {
+ public:
+ virtual int method(int param);
+ virtual int removedMethod(int param);
+ };";
+ $SOURCE1 .= "
+ int RemovedVirtualMethodFromEnd::method(int param) { return param; }
+ int RemovedVirtualMethodFromEnd::removedMethod(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC RemovedVirtualMethodFromEnd
+ {
+ public:
+ virtual int method(int param);
+ int removedMethod(int param);
+ };";
+ $SOURCE2 .= "
+ int RemovedVirtualMethodFromEnd::method(int param) { return param; }
+ int RemovedVirtualMethodFromEnd::removedMethod(int param) { return param; }";
+
+ # Removed_Last_Virtual_Method
+ $HEADER1 .= "
+ class $DECL_SPEC RemovedLastVirtualMethod
+ {
+ public:
+ int method(int param);
+ virtual int removedMethod(int param);
+ };";
+ $SOURCE1 .= "
+ int RemovedLastVirtualMethod::method(int param) { return param; }";
+ $SOURCE1 .= "
+ int RemovedLastVirtualMethod::removedMethod(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC RemovedLastVirtualMethod
+ {
+ public:
+ int method(int param);
+ int removedMethod(int param);
+ };";
+ $SOURCE2 .= "
+ int RemovedLastVirtualMethod::method(int param) { return param; }";
+ $SOURCE2 .= "
+ int RemovedLastVirtualMethod::removedMethod(int param) { return param; }";
+
+ # Virtual_Table_Size
+ $HEADER1 .= "
+ class $DECL_SPEC VirtualTableSize
+ {
+ public:
+ virtual int method1(int param);
+ virtual int method2(int param);
+ };
+ class $DECL_SPEC VirtualTableSize_SubClass: public VirtualTableSize
+ {
+ public:
+ virtual int method3(int param);
+ virtual int method4(int param);
+ };";
+ $SOURCE1 .= "
+ int VirtualTableSize::method1(int param) { return param; }
+ int VirtualTableSize::method2(int param) { return param; }
+ int VirtualTableSize_SubClass::method3(int param) { return param; }
+ int VirtualTableSize_SubClass::method4(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC VirtualTableSize
+ {
+ public:
+ virtual int method1(int param);
+ virtual int method2(int param);
+ virtual int addedMethod(int param);
+ };
+ class $DECL_SPEC VirtualTableSize_SubClass: public VirtualTableSize
+ {
+ public:
+ virtual int method3(int param);
+ virtual int method4(int param);
+ };";
+ $SOURCE2 .= "
+ int VirtualTableSize::method1(int param) { return param; }
+ int VirtualTableSize::method2(int param) { return param; }
+ int VirtualTableSize::addedMethod(int param) { return param; }
+ int VirtualTableSize_SubClass::method3(int param) { return param; }
+ int VirtualTableSize_SubClass::method4(int param) { return param; }";
+
+ # Virtual_Method_Position
+ $HEADER1 .= "
+ class $DECL_SPEC VirtualMethodPosition
+ {
+ public:
+ virtual int method1(int param);
+ virtual int method2(int param);
+ };";
+ $SOURCE1 .= "
+ int VirtualMethodPosition::method1(int param) { return param; }";
+ $SOURCE1 .= "
+ int VirtualMethodPosition::method2(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC VirtualMethodPosition
+ {
+ public:
+ virtual int method2(int param);
+ virtual int method1(int param);
+ };";
+ $SOURCE2 .= "
+ int VirtualMethodPosition::method1(int param) { return param; }";
+ $SOURCE2 .= "
+ int VirtualMethodPosition::method2(int param) { return param; }";
+
+ # Pure_Virtual_Method_Position
+ $HEADER1 .= "
+ class $DECL_SPEC PureVirtualFunctionPosition {
+ public:
+ virtual int method1(int param)=0;
+ virtual int method2(int param)=0;
+ int method3(int param);
+ };";
+ $SOURCE1 .= "
+ int PureVirtualFunctionPosition::method3(int param) { return method1(7)+method2(7); }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC PureVirtualFunctionPosition {
+ public:
+ virtual int method2(int param)=0;
+ virtual int method1(int param)=0;
+ int method3(int param);
+ };";
+ $SOURCE2 .= "
+ int PureVirtualFunctionPosition::method3(int param) { return method1(7)+method2(7); }";
+
+ # Virtual_Method_Position
+ $HEADER1 .= "
+ class $DECL_SPEC VirtualFunctionPosition {
+ public:
+ virtual int method1(int param);
+ virtual int method2(int param);
+ };";
+ $SOURCE1 .= "
+ int VirtualFunctionPosition::method1(int param) { return 1; }
+ int VirtualFunctionPosition::method2(int param) { return 2; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC VirtualFunctionPosition {
+ public:
+ virtual int method2(int param);
+ virtual int method1(int param);
+ };";
+ $SOURCE2 .= "
+ int VirtualFunctionPosition::method1(int param) { return 1; }
+ int VirtualFunctionPosition::method2(int param) { return 2; }";
+
+ # Virtual_Method_Position (safe)
+ $HEADER1 .= "
+ class $DECL_SPEC VirtualFunctionPositionSafe_Base {
+ public:
+ virtual int method1(int param);
+ virtual int method2(int param);
+ };
+ class $DECL_SPEC VirtualFunctionPositionSafe: public VirtualFunctionPositionSafe_Base {
+ public:
+ virtual int method1(int param);
+ virtual int method2(int param);
+ };";
+ $SOURCE1 .= "
+ int VirtualFunctionPositionSafe_Base::method1(int param) { return param; }
+ int VirtualFunctionPositionSafe_Base::method2(int param) { return param; }
+ int VirtualFunctionPositionSafe::method1(int param) { return param; }
+ int VirtualFunctionPositionSafe::method2(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC VirtualFunctionPositionSafe_Base {
+ public:
+ virtual int method1(int param);
+ virtual int method2(int param);
+ };
+ class $DECL_SPEC VirtualFunctionPositionSafe: public VirtualFunctionPositionSafe_Base {
+ public:
+ virtual int method2(int param);
+ virtual int method1(int param);
+ };";
+ $SOURCE2 .= "
+ int VirtualFunctionPositionSafe_Base::method1(int param) { return param; }
+ int VirtualFunctionPositionSafe_Base::method2(int param) { return param; }
+ int VirtualFunctionPositionSafe::method1(int param) { return param; }
+ int VirtualFunctionPositionSafe::method2(int param) { return param; }";
+
+ # Overridden_Virtual_Method
+ $HEADER1 .= "
+ class $DECL_SPEC OverriddenVirtualMethod_Base {
+ public:
+ virtual int method1(int param);
+ virtual int method2(int param);
+ };
+ class $DECL_SPEC OverriddenVirtualMethod: public OverriddenVirtualMethod_Base {
+ public:
+ OverriddenVirtualMethod();
+ virtual int method3(int param);
+ };";
+ $SOURCE1 .= "
+ int OverriddenVirtualMethod_Base::method1(int param) { return param; }
+ int OverriddenVirtualMethod_Base::method2(int param) { return param; }
+ OverriddenVirtualMethod::OverriddenVirtualMethod() {}
+ int OverriddenVirtualMethod::method3(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC OverriddenVirtualMethod_Base {
+ public:
+ virtual int method1(int param);
+ virtual int method2(int param);
+ };
+ class $DECL_SPEC OverriddenVirtualMethod:public OverriddenVirtualMethod_Base {
+ OverriddenVirtualMethod();
+ virtual int method2(int param);
+ virtual int method3(int param);
+ };";
+ $SOURCE2 .= "
+ int OverriddenVirtualMethod_Base::method1(int param) { return param; }
+ int OverriddenVirtualMethod_Base::method2(int param) { return param; }
+ OverriddenVirtualMethod::OverriddenVirtualMethod() {}
+ int OverriddenVirtualMethod::method2(int param) { return param; }
+ int OverriddenVirtualMethod::method3(int param) { return param; }";
+
+ # Overridden_Virtual_Method_B (+ removed)
+ $HEADER1 .= "
+
+ class $DECL_SPEC OverriddenVirtualMethodB: public OverriddenVirtualMethod_Base {
+ public:
+ OverriddenVirtualMethodB();
+ virtual int method2(int param);
+ virtual int method3(int param);
+ };";
+ $SOURCE1 .= "
+ OverriddenVirtualMethodB::OverriddenVirtualMethodB() {}
+ int OverriddenVirtualMethodB::method2(int param) { return param; }
+ int OverriddenVirtualMethodB::method3(int param) { return param; }";
+
+ $HEADER2 .= "
+
+ class $DECL_SPEC OverriddenVirtualMethodB:public OverriddenVirtualMethod_Base {
+ public:
+ OverriddenVirtualMethodB();
+ virtual int method3(int param);
+ };";
+ $SOURCE2 .= "
+ OverriddenVirtualMethodB::OverriddenVirtualMethodB() {}
+ int OverriddenVirtualMethodB::method3(int param) { return param; }";
+
+ # Size
+ $HEADER1 .= "
+ struct $DECL_SPEC TypeSize
+ {
+ public:
+ TypeSize method(TypeSize param);
+ int i[5];
+ long j;
+ double k;
+ TypeSize* p;
+ };";
+ $SOURCE1 .= "
+ TypeSize TypeSize::method(TypeSize param) { return param; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC TypeSize
+ {
+ public:
+ TypeSize method(TypeSize param);
+ int i[15];
+ long j;
+ double k;
+ TypeSize* p;
+ int added_member;
+ };";
+ $SOURCE2 .= "
+ TypeSize TypeSize::method(TypeSize param) { return param; }";
+
+ # Size_Of_Allocable_Class_Increased
+ $HEADER1 .= "
+ class $DECL_SPEC AllocableClassSize
+ {
+ public:
+ AllocableClassSize();
+ int method();
+ double p[5];
+ };";
+ $SOURCE1 .= "
+ AllocableClassSize::AllocableClassSize() { }";
+ $SOURCE1 .= "
+ int AllocableClassSize::method() { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC AllocableClassSize
+ {
+ public:
+ AllocableClassSize();
+ int method();
+ double p[15];
+ };";
+ $SOURCE2 .= "
+ AllocableClassSize::AllocableClassSize() { }";
+ $SOURCE2 .= "
+ int AllocableClassSize::method() { return 0; }";
+
+ # Size_Of_Allocable_Class_Decreased (decreased size, has derived class, has public members)
+ $HEADER1 .= "
+ class $DECL_SPEC DecreasedClassSize
+ {
+ public:
+ DecreasedClassSize();
+ int method();
+ double p[15];
+ };";
+ $SOURCE1 .= "
+ DecreasedClassSize::DecreasedClassSize() { }";
+ $SOURCE1 .= "
+ int DecreasedClassSize::method() { return 0; }";
+ $HEADER1 .= "
+ class $DECL_SPEC DecreasedClassSize_SubClass: public DecreasedClassSize
+ {
+ public:
+ DecreasedClassSize_SubClass();
+ int method();
+ int f;
+ };";
+ $SOURCE1 .= "
+ DecreasedClassSize_SubClass::DecreasedClassSize_SubClass() { f=7; }";
+ $SOURCE1 .= "
+ int DecreasedClassSize_SubClass::method() { return f; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC DecreasedClassSize
+ {
+ public:
+ DecreasedClassSize();
+ int method();
+ double p[5];
+ };";
+ $SOURCE2 .= "
+ DecreasedClassSize::DecreasedClassSize() { }";
+ $SOURCE2 .= "
+ int DecreasedClassSize::method() { return 0; }";
+ $HEADER2 .= "
+ class $DECL_SPEC DecreasedClassSize_SubClass: public DecreasedClassSize
+ {
+ public:
+ DecreasedClassSize_SubClass();
+ int method();
+ int f;
+ };";
+ $SOURCE2 .= "
+ DecreasedClassSize_SubClass::DecreasedClassSize_SubClass() { f=7; }";
+ $SOURCE2 .= "
+ int DecreasedClassSize_SubClass::method() { return f; }";
+
+ # Size_Of_Copying_Class
+ $HEADER1 .= "
+ class $DECL_SPEC CopyingClassSize
+ {
+ public:
+ int method();
+ int p[5];
+ };";
+ $SOURCE1 .= "
+ int CopyingClassSize::method() { return p[4]; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC CopyingClassSize
+ {
+ public:
+ int method();
+ int p[15];
+ };";
+ $SOURCE2 .= "
+ int CopyingClassSize::method() { return p[10]; }";
+
+ # Base_Class_Became_Virtually_Inherited
+ $HEADER1 .= "
+ class $DECL_SPEC BecameVirtualBase
+ {
+ public:
+ BecameVirtualBase();
+ int method();
+ double p[5];
+ };";
+ $SOURCE1 .= "
+ BecameVirtualBase::BecameVirtualBase() { }";
+ $SOURCE1 .= "
+ int BecameVirtualBase::method() { return 0; }";
+ $HEADER1 .= "
+ class $DECL_SPEC AddedVirtualBase1:public BecameVirtualBase
+ {
+ public:
+ AddedVirtualBase1();
+ int method();
+ };";
+ $SOURCE1 .= "
+ AddedVirtualBase1::AddedVirtualBase1() { }";
+ $SOURCE1 .= "
+ int AddedVirtualBase1::method() { return 0; }";
+ $HEADER1 .= "
+ class $DECL_SPEC AddedVirtualBase2: public BecameVirtualBase
+ {
+ public:
+ AddedVirtualBase2();
+ int method();
+ };";
+ $SOURCE1 .= "
+ AddedVirtualBase2::AddedVirtualBase2() { }";
+ $SOURCE1 .= "
+ int AddedVirtualBase2::method() { return 0; }";
+ $HEADER1 .= "
+ class $DECL_SPEC BaseClassBecameVirtuallyInherited:public AddedVirtualBase1, public AddedVirtualBase2
+ {
+ public:
+ BaseClassBecameVirtuallyInherited();
+ };";
+ $SOURCE1 .= "
+ BaseClassBecameVirtuallyInherited::BaseClassBecameVirtuallyInherited() { }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC BecameVirtualBase
+ {
+ public:
+ BecameVirtualBase();
+ int method();
+ double p[5];
+ };";
+ $SOURCE2 .= "
+ BecameVirtualBase::BecameVirtualBase() { }";
+ $SOURCE2 .= "
+ int BecameVirtualBase::method() { return 0; }";
+ $HEADER2 .= "
+ class $DECL_SPEC AddedVirtualBase1:public virtual BecameVirtualBase
+ {
+ public:
+ AddedVirtualBase1();
+ int method();
+ };";
+ $SOURCE2 .= "
+ AddedVirtualBase1::AddedVirtualBase1() { }";
+ $SOURCE2 .= "
+ int AddedVirtualBase1::method() { return 0; }";
+ $HEADER2 .= "
+ class $DECL_SPEC AddedVirtualBase2: public virtual BecameVirtualBase
+ {
+ public:
+ AddedVirtualBase2();
+ int method();
+ };";
+ $SOURCE2 .= "
+ AddedVirtualBase2::AddedVirtualBase2() { }";
+ $SOURCE2 .= "
+ int AddedVirtualBase2::method() { return 0; }";
+ $HEADER2 .= "
+ class $DECL_SPEC BaseClassBecameVirtuallyInherited:public AddedVirtualBase1, public AddedVirtualBase2
+ {
+ public:
+ BaseClassBecameVirtuallyInherited();
+ };";
+ $SOURCE2 .= "
+ BaseClassBecameVirtuallyInherited::BaseClassBecameVirtuallyInherited() { }";
+
+ # Added_Base_Class, Removed_Base_Class
+ $HEADER1 .= "
+ class $DECL_SPEC BaseClass
+ {
+ public:
+ BaseClass();
+ int method();
+ double p[5];
+ };
+ class $DECL_SPEC RemovedBaseClass
+ {
+ public:
+ RemovedBaseClass();
+ int method();
+ };
+ class $DECL_SPEC ChangedBaseClass:public BaseClass, public RemovedBaseClass
+ {
+ public:
+ ChangedBaseClass();
+ };";
+ $SOURCE1 .= "
+ BaseClass::BaseClass() { }
+ int BaseClass::method() { return 0; }
+ RemovedBaseClass::RemovedBaseClass() { }
+ int RemovedBaseClass::method() { return 0; }
+ ChangedBaseClass::ChangedBaseClass() { }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC BaseClass
+ {
+ public:
+ BaseClass();
+ int method();
+ double p[5];
+ };
+ class $DECL_SPEC AddedBaseClass
+ {
+ public:
+ AddedBaseClass();
+ int method();
+ };
+ class $DECL_SPEC ChangedBaseClass:public BaseClass, public AddedBaseClass
+ {
+ public:
+ ChangedBaseClass();
+ };";
+ $SOURCE2 .= "
+ BaseClass::BaseClass() { }
+ int BaseClass::method() { return 0; }
+ AddedBaseClass::AddedBaseClass() { }
+ int AddedBaseClass::method() { return 0; }
+ ChangedBaseClass::ChangedBaseClass() { }";
+
+ # Added_Base_Class_And_Shift, Removed_Base_Class_And_Shift
+ $HEADER1 .= "
+ struct $DECL_SPEC BaseClass2
+ {
+ BaseClass2();
+ int method();
+ double p[15];
+ };
+ class $DECL_SPEC ChangedBaseClassAndSize:public BaseClass
+ {
+ public:
+ ChangedBaseClassAndSize();
+ };";
+ $SOURCE1 .= "
+ BaseClass2::BaseClass2() { }
+ int BaseClass2::method() { return 0; }
+ ChangedBaseClassAndSize::ChangedBaseClassAndSize() { }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC BaseClass2
+ {
+ BaseClass2();
+ int method();
+ double p[15];
+ };
+ class $DECL_SPEC ChangedBaseClassAndSize:public BaseClass2
+ {
+ public:
+ ChangedBaseClassAndSize();
+ };";
+ $SOURCE2 .= "
+ BaseClass2::BaseClass2() { }
+ int BaseClass2::method() { return 0; }
+ ChangedBaseClassAndSize::ChangedBaseClassAndSize() { }";
+
+ # Added_Field_And_Size
+ $HEADER1 .= "
+ struct $DECL_SPEC AddedFieldAndSize
+ {
+ int method(AddedFieldAndSize param);
+ double i, j, k;
+ AddedFieldAndSize* p;
+ };";
+ $SOURCE1 .= "
+ int AddedFieldAndSize::method(AddedFieldAndSize param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC AddedFieldAndSize
+ {
+ int method(AddedFieldAndSize param);
+ double i, j, k;
+ AddedFieldAndSize* p;
+ int added_member1;
+ long long added_member2;
+ };";
+ $SOURCE2 .= "
+ int AddedFieldAndSize::method(AddedFieldAndSize param) { return 0; }";
+
+ # Added_Field
+ $HEADER1 .= "
+ class $DECL_SPEC ObjectAddedMember
+ {
+ public:
+ int method(int param);
+ double i, j, k;
+ AddedFieldAndSize* p;
+ };";
+ $SOURCE1 .= "
+ int ObjectAddedMember::method(int param) { return param; }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC ObjectAddedMember
+ {
+ public:
+ int method(int param);
+ double i, j, k;
+ AddedFieldAndSize* p;
+ int added_member1;
+ long long added_member2;
+ };";
+ $SOURCE2 .= "
+ int ObjectAddedMember::method(int param) { return param; }";
+
+ # Added_Field (safe)
+ $HEADER1 .= "
+ struct $DECL_SPEC AddedBitfield
+ {
+ int method(AddedBitfield param);
+ double i, j, k;
+ int b1 : 32;
+ int b2 : 31;
+ AddedBitfield* p;
+ };";
+ $SOURCE1 .= "
+ int AddedBitfield::method(AddedBitfield param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC AddedBitfield
+ {
+ int method(AddedBitfield param);
+ double i, j, k;
+ int b1 : 32;
+ int b2 : 31;
+ int added_bitfield : 1;
+ int added_bitfield2 : 1;
+ AddedBitfield* p;
+ };";
+ $SOURCE2 .= "
+ int AddedBitfield::method(AddedBitfield param) { return 0; }";
+
+ # Bit_Field_Size
+ $HEADER1 .= "
+ struct $DECL_SPEC BitfieldSize
+ {
+ int method(BitfieldSize param);
+ short changed_bitfield : 1;
+ };";
+ $SOURCE1 .= "
+ int BitfieldSize::method(BitfieldSize param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC BitfieldSize
+ {
+ int method(BitfieldSize param);
+ short changed_bitfield : 7;
+ };";
+ $SOURCE2 .= "
+ int BitfieldSize::method(BitfieldSize param) { return 0; }";
+
+ # Removed_Field
+ $HEADER1 .= "
+ struct $DECL_SPEC RemovedBitfield
+ {
+ int method(RemovedBitfield param);
+ double i, j, k;
+ int b1 : 32;
+ int b2 : 31;
+ int removed_bitfield : 1;
+ RemovedBitfield* p;
+ };";
+ $SOURCE1 .= "
+ int RemovedBitfield::method(RemovedBitfield param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC RemovedBitfield
+ {
+ int method(RemovedBitfield param);
+ double i, j, k;
+ int b1 : 32;
+ int b2 : 31;
+ RemovedBitfield* p;
+ };";
+ $SOURCE2 .= "
+ int RemovedBitfield::method(RemovedBitfield param) { return 0; }";
+
+ # Removed_Middle_Field
+ $HEADER1 .= "
+ struct $DECL_SPEC RemovedMiddleBitfield
+ {
+ int method(RemovedMiddleBitfield param);
+ double i, j, k;
+ int b1 : 32;
+ int removed_middle_bitfield : 1;
+ int b2 : 31;
+ RemovedMiddleBitfield* p;
+ };";
+ $SOURCE1 .= "
+ int RemovedMiddleBitfield::method(RemovedMiddleBitfield param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC RemovedMiddleBitfield
+ {
+ int method(RemovedMiddleBitfield param);
+ double i, j, k;
+ int b1 : 32;
+ int b2 : 31;
+ RemovedMiddleBitfield* p;
+ };";
+ $SOURCE2 .= "
+ int RemovedMiddleBitfield::method(RemovedMiddleBitfield param) { return 0; }";
+
+ # Added_Middle_Field_And_Size
+ $HEADER1 .= "
+ struct $DECL_SPEC AddedMiddleFieldAndSize
+ {
+ int method(AddedMiddleFieldAndSize param);
+ int i;
+ long j;
+ double k;
+ AddedMiddleFieldAndSize* p;
+ };";
+ $SOURCE1 .= "
+ int AddedMiddleFieldAndSize::method(AddedMiddleFieldAndSize param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC AddedMiddleFieldAndSize
+ {
+ int method(AddedMiddleFieldAndSize param);
+ int i;
+ int added_middle_member;
+ long j;
+ double k;
+ AddedMiddleFieldAndSize* p;
+ };";
+ $SOURCE2 .= "
+ int AddedMiddleFieldAndSize::method(AddedMiddleFieldAndSize param) { return 0; }";
+
+ # Added_Field (padding)
+ $HEADER1 .= "
+ struct $DECL_SPEC AddedMiddlePaddedField
+ {
+ int method(int param);
+ short i;
+ long j;
+ double k;
+ };";
+ $SOURCE1 .= "
+ int AddedMiddlePaddedField::method(int param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC AddedMiddlePaddedField
+ {
+ int method(int param);
+ short i;
+ short added_padded_field;
+ long j;
+ double k;
+ };";
+ $SOURCE2 .= "
+ int AddedMiddlePaddedField::method(int param) { return 0; }";
+
+ # Added_Field (tail padding)
+ $HEADER1 .= "
+ struct $DECL_SPEC AddedTailField
+ {
+ int method(int param);
+ int i1, i2, i3, i4, i5, i6, i7;
+ short s;
+ };";
+ $SOURCE1 .= "
+ int AddedTailField::method(int param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC AddedTailField
+ {
+ int method(int param);
+ int i1, i2, i3, i4, i5, i6, i7;
+ short s;
+ short added_tail_field;
+ };";
+ $SOURCE2 .= "
+ int AddedTailField::method(int param) { return 0; }";
+
+ # Test Alignment
+ $HEADER1 .= "
+ struct $DECL_SPEC TestAlignment
+ {
+ int method(int param);
+ short s:9;
+ short j:9;
+ char c;
+ short t:9;
+ short u:9;
+ char d;
+ };";
+ $SOURCE1 .= "
+ int TestAlignment::method(int param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC TestAlignment
+ {
+ int method(int param);
+ short s:9;
+ short j:9;
+ char c;
+ short t:9;
+ short u:9;
+ char d;
+ };";
+ $SOURCE2 .= "
+ int TestAlignment::method(int param) { return 0; }";
+
+ # Renamed_Field
+ $HEADER1 .= "
+ struct $DECL_SPEC RenamedField
+ {
+ int method(RenamedField param);
+ long i;
+ long j;
+ double k;
+ RenamedField* p;
+ };";
+ $SOURCE1 .= "
+ int RenamedField::method(RenamedField param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC RenamedField
+ {
+ int method(RenamedField param);
+ long renamed_member;
+ long j;
+ double k;
+ RenamedField* p;
+ };";
+ $SOURCE2 .= "
+ int RenamedField::method(RenamedField param) { return 0; }";
+
+ # Removed_Field_And_Size
+ $HEADER1 .= "
+ struct $DECL_SPEC RemovedFieldAndSize
+ {
+ int method(RemovedFieldAndSize param);
+ double i, j, k;
+ RemovedFieldAndSize* p;
+ int removed_member1;
+ long removed_member2;
+ };";
+ $SOURCE1 .= "
+ int RemovedFieldAndSize::method(RemovedFieldAndSize param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC RemovedFieldAndSize
+ {
+ int method(RemovedFieldAndSize param);
+ double i, j, k;
+ RemovedFieldAndSize* p;
+ };";
+ $SOURCE2 .= "
+ int RemovedFieldAndSize::method(RemovedFieldAndSize param) { return 0; }";
+
+ # Field Position
+ $HEADER1 .= "
+ struct $DECL_SPEC MovedField
+ {
+ int method(int param);
+ double i;
+ int j;
+ };";
+ $SOURCE1 .= "
+ int MovedField::method(int param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC MovedField
+ {
+ int method(int param);
+ int j;
+ double i;
+ };";
+ $SOURCE2 .= "
+ int MovedField::method(int param) { return 0; }";
+
+ # Removed_Middle_Field_And_Size
+ $HEADER1 .= "
+ struct $DECL_SPEC RemovedMiddleFieldAndSize
+ {
+ int method(RemovedMiddleFieldAndSize param);
+ int i;
+ int removed_middle_member;
+ long j;
+ double k;
+ RemovedMiddleFieldAndSize* p;
+ };";
+ $SOURCE1 .= "
+ int RemovedMiddleFieldAndSize::method(RemovedMiddleFieldAndSize param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC RemovedMiddleFieldAndSize
+ {
+ int method(RemovedMiddleFieldAndSize param);
+ int i;
+ long j;
+ double k;
+ RemovedMiddleFieldAndSize* p;
+ };";
+ $SOURCE2 .= "
+ int RemovedMiddleFieldAndSize::method(RemovedMiddleFieldAndSize param) { return 0; }";
+
+ # Enum_Member_Value
+ $HEADER1 .= "
+ enum EnumMemberValue
+ {
+ MEMBER_1=1,
+ MEMBER_2=2
+ };";
+ $HEADER1 .= "
+ $DECL_SPEC int enumMemberValueChange(enum EnumMemberValue param);";
+ $SOURCE1 .= "
+ int enumMemberValueChange(enum EnumMemberValue param) { return 0; }";
+
+ $HEADER2 .= "
+ enum EnumMemberValue
+ {
+ MEMBER_1=2,
+ MEMBER_2=1
+ };";
+ $HEADER2 .= "
+ $DECL_SPEC int enumMemberValueChange(enum EnumMemberValue param);";
+ $SOURCE2 .= "
+ int enumMemberValueChange(enum EnumMemberValue param) { return 0; }";
+
+ # Enum_Member_Name
+ $HEADER1 .= "
+ enum EnumMemberRename
+ {
+ BRANCH_1=1,
+ BRANCH_2=2
+ };";
+ $HEADER1 .= "
+ $DECL_SPEC int enumMemberRename(enum EnumMemberRename param);";
+ $SOURCE1 .= "
+ int enumMemberRename(enum EnumMemberRename param) { return 0; }";
+
+ $HEADER2 .= "
+ enum EnumMemberRename
+ {
+ BRANCH_FIRST=1,
+ BRANCH_SECOND=2
+ };";
+ $HEADER2 .= "
+ $DECL_SPEC int enumMemberRename(enum EnumMemberRename param);";
+ $SOURCE2 .= "
+ int enumMemberRename(enum EnumMemberRename param) { return 0; }";
+
+ # Field_Type_And_Size
+ $HEADER1 .= "
+ struct $DECL_SPEC FieldTypeAndSize
+ {
+ int method(FieldTypeAndSize param);
+ int i;
+ long j;
+ double k;
+ FieldTypeAndSize* p;
+ };";
+ $SOURCE1 .= "
+ int FieldTypeAndSize::method(FieldTypeAndSize param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC FieldTypeAndSize
+ {
+ int method(FieldTypeAndSize param);
+ long long i;
+ long j;
+ double k;
+ FieldTypeAndSize* p;
+ };";
+ $SOURCE2 .= "
+ int FieldTypeAndSize::method(FieldTypeAndSize param) { return 0; }";
+
+ # Member_Type
+ $HEADER1 .= "
+ struct $DECL_SPEC MemberType
+ {
+ int method(MemberType param);
+ int i;
+ long j;
+ double k;
+ MemberType* p;
+ };";
+ $SOURCE1 .= "
+ int MemberType::method(MemberType param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC MemberType
+ {
+ int method(MemberType param);
+ float i;
+ long j;
+ double k;
+ MemberType* p;
+ };";
+ $SOURCE2 .= "
+ int MemberType::method(MemberType param) { return 0; }";
+
+ # Field_BaseType
+ $HEADER1 .= "
+ struct $DECL_SPEC FieldBaseType
+ {
+ int method(FieldBaseType param);
+ int *i;
+ long j;
+ double k;
+ FieldBaseType* p;
+ };";
+ $SOURCE1 .= "
+ int FieldBaseType::method(FieldBaseType param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC FieldBaseType
+ {
+ int method(FieldBaseType param);
+ long long *i;
+ long j;
+ double k;
+ FieldBaseType* p;
+ };";
+ $SOURCE2 .= "
+ int FieldBaseType::method(FieldBaseType param) { return 0; }";
+
+ # Field_PointerLevel_Increased (and size)
+ $HEADER1 .= "
+ struct $DECL_SPEC FieldPointerLevelAndSize
+ {
+ int method(FieldPointerLevelAndSize param);
+ long long i;
+ long j;
+ double k;
+ FieldPointerLevelAndSize* p;
+ };";
+ $SOURCE1 .= "
+ int FieldPointerLevelAndSize::method(FieldPointerLevelAndSize param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC FieldPointerLevelAndSize
+ {
+ int method(FieldPointerLevelAndSize param);
+ long long *i;
+ long j;
+ double k;
+ FieldPointerLevelAndSize* p;
+ };";
+ $SOURCE2 .= "
+ int FieldPointerLevelAndSize::method(FieldPointerLevelAndSize param) { return 0; }";
+
+ # Field_PointerLevel
+ $HEADER1 .= "
+ struct $DECL_SPEC FieldPointerLevel
+ {
+ int method(FieldPointerLevel param);
+ int **i;
+ long j;
+ double k;
+ FieldPointerLevel* p;
+ };";
+ $SOURCE1 .= "
+ int FieldPointerLevel::method(FieldPointerLevel param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC FieldPointerLevel
+ {
+ int method(FieldPointerLevel param);
+ int *i;
+ long j;
+ double k;
+ FieldPointerLevel* p;
+ };";
+ $SOURCE2 .= "
+ int FieldPointerLevel::method(FieldPointerLevel param) { return 0; }";
+
+ # Added_Interface (method)
+ $HEADER1 .= "
+ struct $DECL_SPEC AddedInterface
+ {
+ int method(AddedInterface param);
+ int i;
+ long j;
+ double k;
+ AddedInterface* p;
+ };";
+ $SOURCE1 .= "
+ int AddedInterface::method(AddedInterface param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC AddedInterface
+ {
+ int method(AddedInterface param);
+ int added_func(AddedInterface param);
+ int i;
+ long j;
+ double k;
+ AddedInterface* p;
+ };";
+ $SOURCE2 .= "
+ int AddedInterface::method(AddedInterface param) { return 0; }";
+ $SOURCE2 .= "
+ int AddedInterface::added_func(AddedInterface param) { return 0; }";
+
+ # Added_Interface (function)
+ $HEADER2 .= "
+ $DECL_SPEC int addedFunc2(void *** param);";
+ $SOURCE2 .= "
+ int addedFunc2(void *** param) { return 0; }";
+
+ # Added_Interface (global variable)
+ $HEADER1 .= "
+ struct $DECL_SPEC AddedVariable
+ {
+ int method(AddedVariable param);
+ int i1, i2;
+ long j;
+ double k;
+ AddedVariable* p;
+ };";
+ $SOURCE1 .= "
+ int AddedVariable::method(AddedVariable param) {
+ return i1;
+ }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC AddedVariable
+ {
+ int method(AddedVariable param);
+ static int i1;
+ static int i2;
+ long j;
+ double k;
+ AddedVariable* p;
+ };";
+ $SOURCE2 .= "
+ int AddedVariable::method(AddedVariable param) { return AddedVariable::i1; }";
+ $SOURCE2 .= "
+ int AddedVariable::i1=0;";
+ $SOURCE2 .= "
+ int AddedVariable::i2=0;";
+
+ # Removed_Interface (method)
+ $HEADER1 .= "
+ struct $DECL_SPEC RemovedInterface
+ {
+ int method(RemovedInterface param);
+ int removed_func(RemovedInterface param);
+ int i;
+ long j;
+ double k;
+ RemovedInterface* p;
+ };";
+ $SOURCE1 .= "
+ int RemovedInterface::method(RemovedInterface param) { return 0; }";
+ $SOURCE1 .= "
+ int RemovedInterface::removed_func(RemovedInterface param) { return 0; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC RemovedInterface
+ {
+ int method(RemovedInterface param);
+ int i;
+ long j;
+ double k;
+ RemovedInterface* p;
+ };";
+ $SOURCE2 .= "
+ int RemovedInterface::method(RemovedInterface param) { return 0; }";
+
+ # Removed_Interface (function)
+ $HEADER1 .= "
+ $DECL_SPEC int removedFunc2(void *** param);";
+ $SOURCE1 .= "
+ int removedFunc2(void *** param) { return 0; }";
+
+ # Method_Became_Static
+ $HEADER1 .= "
+ struct $DECL_SPEC MethodBecameStatic
+ {
+ MethodBecameStatic becameStatic(MethodBecameStatic param);
+ int **i;
+ long j;
+ double k;
+ MethodBecameStatic* p;
+ };";
+ $SOURCE1 .= "
+ MethodBecameStatic MethodBecameStatic::becameStatic(MethodBecameStatic param) { return param; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC MethodBecameStatic
+ {
+ static MethodBecameStatic becameStatic(MethodBecameStatic param);
+ int **i;
+ long j;
+ double k;
+ MethodBecameStatic* p;
+ };";
+ $SOURCE2 .= "
+ MethodBecameStatic MethodBecameStatic::becameStatic(MethodBecameStatic param) { return param; }";
+
+ # Method_Became_NonStatic
+ $HEADER1 .= "
+ struct $DECL_SPEC MethodBecameNonStatic
+ {
+ static MethodBecameNonStatic becameNonStatic(MethodBecameNonStatic param);
+ int **i;
+ long j;
+ double k;
+ MethodBecameNonStatic* p;
+ };";
+ $SOURCE1 .= "
+ MethodBecameNonStatic MethodBecameNonStatic::becameNonStatic(MethodBecameNonStatic param) { return param; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC MethodBecameNonStatic
+ {
+ MethodBecameNonStatic becameNonStatic(MethodBecameNonStatic param);
+ int **i;
+ long j;
+ double k;
+ MethodBecameNonStatic* p;
+ };";
+ $SOURCE2 .= "
+ MethodBecameNonStatic MethodBecameNonStatic::becameNonStatic(MethodBecameNonStatic param) { return param; }";
+
+ # Parameter_Type_And_Size
+ $HEADER1 .= "
+ $DECL_SPEC int funcParameterTypeAndSize(int param, int other_param);";
+ $SOURCE1 .= "
+ int funcParameterTypeAndSize(int param, int other_param) { return other_param; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int funcParameterTypeAndSize(long long param, int other_param);";
+ $SOURCE2 .= "
+ int funcParameterTypeAndSize(long long param, int other_param) { return other_param; }";
+
+ # Parameter_Type
+ $HEADER1 .= "
+ $DECL_SPEC int funcParameterType(int param, int other_param);";
+ $SOURCE1 .= "
+ int funcParameterType(int param, int other_param) { return other_param; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int funcParameterType(float param, int other_param);";
+ $SOURCE2 .= "
+ int funcParameterType(float param, int other_param) { return other_param; }";
+
+ # Parameter_BaseType
+ $HEADER1 .= "
+ $DECL_SPEC int funcParameterBaseType(int *param);";
+ $SOURCE1 .= "
+ int funcParameterBaseType(int *param) { return sizeof(*param); }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int funcParameterBaseType(long long *param);";
+ $SOURCE2 .= "
+ int funcParameterBaseType(long long *param) { return sizeof(*param); }";
+
+ # Parameter_PointerLevel
+ $HEADER1 .= "
+ $DECL_SPEC long long funcParameterPointerLevelAndSize(long long param);";
+ $SOURCE1 .= "
+ long long funcParameterPointerLevelAndSize(long long param) { return param; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC long long funcParameterPointerLevelAndSize(long long *param);";
+ $SOURCE2 .= "
+ long long funcParameterPointerLevelAndSize(long long *param) { return param[5]; }";
+
+ # Parameter_PointerLevel
+ $HEADER1 .= "
+ $DECL_SPEC int funcParameterPointerLevel(int *param);";
+ $SOURCE1 .= "
+ int funcParameterPointerLevel(int *param) { return param[5]; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int funcParameterPointerLevel(int **param);";
+ $SOURCE2 .= "
+ int funcParameterPointerLevel(int **param) { return param[5][5]; }";
+
+ # Return_Type_And_Size
+ $HEADER1 .= "
+ $DECL_SPEC int funcReturnTypeAndSize(int param);";
+ $SOURCE1 .= "
+ int funcReturnTypeAndSize(int param) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC long long funcReturnTypeAndSize(int param);";
+ $SOURCE2 .= "
+ long long funcReturnTypeAndSize(int param) { return 0; }";
+
+ # Return_Type
+ $HEADER1 .= "
+ $DECL_SPEC int funcReturnType(int param);";
+ $SOURCE1 .= "
+ int funcReturnType(int param) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC float funcReturnType(int param);";
+ $SOURCE2 .= "
+ float funcReturnType(int param) { return 0.7; }";
+
+ # Return_Type_Became_Void ("int" to "void")
+ $HEADER1 .= "
+ $DECL_SPEC int funcReturnTypeBecameVoid(int param);";
+ $SOURCE1 .= "
+ int funcReturnTypeBecameVoid(int param) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC void funcReturnTypeBecameVoid(int param);";
+ $SOURCE2 .= "
+ void funcReturnTypeBecameVoid(int param) { return; }";
+
+ # Return_BaseType
+ $HEADER1 .= "
+ $DECL_SPEC int* funcReturnBaseType(int param);";
+ $SOURCE1 .= "
+ int* funcReturnBaseType(int param) {
+ int *x = new int[10];
+ return x;
+ }";
+
+ $HEADER2 .= "
+ $DECL_SPEC long long* funcReturnBaseType(int param);";
+ $SOURCE2 .= "
+ long long* funcReturnBaseType(int param) {
+ long long *x = new long long[10];
+ return x;
+ }";
+
+ # Return_PointerLevel
+ $HEADER1 .= "
+ $DECL_SPEC long long funcReturnPointerLevelAndSize(int param);";
+ $SOURCE1 .= "
+ long long funcReturnPointerLevelAndSize(int param) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC long long* funcReturnPointerLevelAndSize(int param);";
+ $SOURCE2 .= "
+ long long* funcReturnPointerLevelAndSize(int param) { return new long long[10]; }";
+
+ # Return_PointerLevel
+ $HEADER1 .= "
+ $DECL_SPEC int* funcReturnPointerLevel(int param);";
+ $SOURCE1 .= "
+ int* funcReturnPointerLevel(int param) { return new int[10]; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int** funcReturnPointerLevel(int param);";
+ $SOURCE2 .= "
+ int** funcReturnPointerLevel(int param) { return new int*[10]; }";
+
+ # Size (anon type)
+ $HEADER1 .= "
+ typedef struct {
+ int i;
+ long j;
+ double k;
+ } AnonTypedef;
+ $DECL_SPEC int funcAnonTypedef(AnonTypedef param);";
+ $SOURCE1 .= "
+ int funcAnonTypedef(AnonTypedef param) { return 0; }";
+
+ $HEADER2 .= "
+ typedef struct {
+ int i;
+ long j;
+ double k;
+ union {
+ int dummy[256];
+ struct {
+ char q_skiptable[256];
+ const char *p;
+ int l;
+ } p;
+ };
+ } AnonTypedef;
+ $DECL_SPEC int funcAnonTypedef(AnonTypedef param);";
+ $SOURCE2 .= "
+ int funcAnonTypedef(AnonTypedef param) { return 0; }";
+
+ # Added_Field (safe: opaque)
+ $HEADER1 .= "
+ struct $DECL_SPEC OpaqueType
+ {
+ public:
+ OpaqueType method(OpaqueType param);
+ int i;
+ long j;
+ double k;
+ OpaqueType* p;
+ };";
+ $SOURCE1 .= "
+ OpaqueType OpaqueType::method(OpaqueType param) { return param; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC OpaqueType
+ {
+ public:
+ OpaqueType method(OpaqueType param);
+ int i;
+ long j;
+ double k;
+ OpaqueType* p;
+ int added_member;
+ };";
+ $SOURCE2 .= "
+ OpaqueType OpaqueType::method(OpaqueType param) { return param; }";
+
+ # Added_Field (safe: internal)
+ $HEADER1 .= "
+ struct $DECL_SPEC InternalType {
+ InternalType method(InternalType param);
+ int i;
+ long j;
+ double k;
+ InternalType* p;
+ };";
+ $SOURCE1 .= "
+ InternalType InternalType::method(InternalType param) { return param; }";
+
+ $HEADER2 .= "
+ struct $DECL_SPEC InternalType {
+ InternalType method(InternalType param);
+ int i;
+ long j;
+ double k;
+ InternalType* p;
+ int added_member;
+ };";
+ $SOURCE2 .= "
+ InternalType InternalType::method(InternalType param) { return param; }";
+
+ # Size (unnamed struct/union fields within structs/unions)
+ $HEADER1 .= "
+ typedef struct {
+ int a;
+ struct {
+ int u1;
+ float u2;
+ };
+ int d;
+ } UnnamedTypeSize;
+ $DECL_SPEC int unnamedTypeSize(UnnamedTypeSize param);";
+ $SOURCE1 .= "
+ int unnamedTypeSize(UnnamedTypeSize param) { return 0; }";
+
+ $HEADER2 .= "
+ typedef struct {
+ int a;
+ struct {
+ long double u1;
+ float u2;
+ };
+ int d;
+ } UnnamedTypeSize;
+ $DECL_SPEC int unnamedTypeSize(UnnamedTypeSize param);";
+ $SOURCE2 .= "
+ int unnamedTypeSize(UnnamedTypeSize param) { return 0; }";
+
+ # constants
+ $HEADER1 .= "
+ #define PUBLIC_CONSTANT \"old_value\"";
+ $HEADER2 .= "
+ #define PUBLIC_CONSTANT \"new_value\"";
+
+ $HEADER1 .= "
+ #define PRIVATE_CONSTANT \"old_value\"
+ #undef PRIVATE_CONSTANT";
+ $HEADER2 .= "
+ #define PRIVATE_CONSTANT \"new_value\"
+ #undef PRIVATE_CONSTANT";
+
+ # Added_Field (union)
+ $HEADER1 .= "
+ union UnionAddedField {
+ int a;
+ struct {
+ int b;
+ float c;
+ };
+ int d;
+ };
+ $DECL_SPEC int unionAddedField(UnionAddedField param);";
+ $SOURCE1 .= "
+ int unionAddedField(UnionAddedField param) { return 0; }";
+
+ $HEADER2 .= "
+ union UnionAddedField {
+ int a;
+ struct {
+ long double x, y;
+ } new_field;
+ struct {
+ int b;
+ float c;
+ };
+ int d;
+ };
+ $DECL_SPEC int unionAddedField(UnionAddedField param);";
+ $SOURCE2 .= "
+ int unionAddedField(UnionAddedField param) { return 0; }";
+
+ # Removed_Field (union)
+ $HEADER1 .= "
+ union UnionRemovedField {
+ int a;
+ struct {
+ long double x, y;
+ } removed_field;
+ struct {
+ int b;
+ float c;
+ };
+ int d;
+ };
+ $DECL_SPEC int unionRemovedField(UnionRemovedField param);";
+ $SOURCE1 .= "
+ int unionRemovedField(UnionRemovedField param) { return 0; }";
+
+ $HEADER2 .= "
+ union UnionRemovedField {
+ int a;
+ struct {
+ int b;
+ float c;
+ };
+ int d;
+ };
+ $DECL_SPEC int unionRemovedField(UnionRemovedField param);";
+ $SOURCE2 .= "
+ int unionRemovedField(UnionRemovedField param) { return 0; }";
+
+ # Added (typedef change)
+ $HEADER1 .= "
+ typedef float TYPEDEF_TYPE;
+ $DECL_SPEC int parameterTypedefChange(TYPEDEF_TYPE param);";
+ $SOURCE1 .= "
+ int parameterTypedefChange(TYPEDEF_TYPE param) { return 1; }";
+
+ $HEADER2 .= "
+ typedef int TYPEDEF_TYPE;
+ $DECL_SPEC int parameterTypedefChange(TYPEDEF_TYPE param);";
+ $SOURCE2 .= "
+ int parameterTypedefChange(TYPEDEF_TYPE param) { return 1; }";
+
+ # Parameter_Default_Value_Changed
+ $HEADER1 .= "
+ $DECL_SPEC int parameterDefaultValueChanged(int param = 0xf00f); ";
+ $SOURCE1 .= "
+ int parameterDefaultValueChanged(int param) { return param; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int parameterDefaultValueChanged(int param = 0xf00b); ";
+ $SOURCE2 .= "
+ int parameterDefaultValueChanged(int param) { return param; }";
+
+ # Parameter_Default_Value_Changed (char const *)
+ $HEADER1 .= "
+ $DECL_SPEC int parameterDefaultStringValueChanged(char const* param = \" str 1 \"); ";
+ $SOURCE1 .= "
+ int parameterDefaultStringValueChanged(char const* param) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int parameterDefaultStringValueChanged(char const* param = \" str 2 \"); ";
+ $SOURCE2 .= "
+ int parameterDefaultStringValueChanged(char const* param) { return 0; }";
+
+ # Parameter_Default_Value_Removed
+ $HEADER1 .= "
+ $DECL_SPEC int parameterDefaultValueRemoved(int param = 0xf00f);
+ ";
+ $SOURCE1 .= "
+ int parameterDefaultValueRemoved(int param) { return param; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int parameterDefaultValueRemoved(int param);";
+ $SOURCE2 .= "
+ int parameterDefaultValueRemoved(int param) { return param; }";
+
+ # Field_Type (typedefs in member type)
+ $HEADER1 .= "
+ typedef float TYPEDEF_TYPE_2;
+ struct $DECL_SPEC FieldTypedefChange{
+ public:
+ TYPEDEF_TYPE_2 m;
+ TYPEDEF_TYPE_2 n;
+ };
+ $DECL_SPEC int fieldTypedefChange(FieldTypedefChange param);";
+ $SOURCE1 .= "
+ int fieldTypedefChange(FieldTypedefChange param) { return 1; }";
+
+ $HEADER2 .= "
+ typedef int TYPEDEF_TYPE_2;
+ struct $DECL_SPEC FieldTypedefChange{
+ public:
+ TYPEDEF_TYPE_2 m;
+ TYPEDEF_TYPE_2 n;
+ };
+ $DECL_SPEC int fieldTypedefChange(FieldTypedefChange param);";
+ $SOURCE2 .= "
+ int fieldTypedefChange(FieldTypedefChange param) { return 1; }";
+
+ # Callback (testCallback symbol should be affected
+ # instead of callback1 and callback2)
+ $HEADER1 .= "
+ class $DECL_SPEC Callback {
+ public:
+ virtual int callback1(int x, int y)=0;
+ virtual int callback2(int x, int y)=0;
+ };
+ $DECL_SPEC int testCallback(Callback* p);";
+ $SOURCE1 .= "
+ int testCallback(Callback* p) {
+ p->callback2(1, 2);
+ return 0;
+ }";
+
+ $HEADER2 .= "
+ class $DECL_SPEC Callback {
+ public:
+ virtual int callback1(int x, int y)=0;
+ virtual int added_callback(int x, int y)=0;
+ virtual int callback2(int x, int y)=0;
+ };
+ $DECL_SPEC int testCallback(Callback* p);";
+ $SOURCE2 .= "
+ int testCallback(Callback* p) {
+ p->callback2(1, 2);
+ return 0;
+ }";
+
+ # End namespace
+ $HEADER1 .= "\n}\n";
+ $HEADER2 .= "\n}\n";
+ $SOURCE1 .= "\n}\n";
+ $SOURCE2 .= "\n}\n";
+
+ runTests("libsample_cpp", "C++", $HEADER1, $SOURCE1, $HEADER2, $SOURCE2, "TestNS::OpaqueType", "_ZN6TestNS12InternalType6methodES0_");
+}
+
+sub testC()
+{
+ printMsg("INFO", "\nverifying detectable C library changes");
+ my ($HEADER1, $SOURCE1, $HEADER2, $SOURCE2) = ();
+ my $DECL_SPEC = ($OSgroup eq "windows")?"__declspec( dllexport )":"";
+ my $EXTERN = ($OSgroup eq "windows")?"extern ":"";
+
+ # Parameter_Type (int to "int const")
+ $HEADER1 .= "
+ $DECL_SPEC void parameterBecameConstInt(int arg);";
+ $SOURCE1 .= "
+ void parameterBecameConstInt(int arg) { }";
+
+ $HEADER2 .= "
+ $DECL_SPEC void parameterBecameConstInt(const int arg);";
+ $SOURCE2 .= "
+ void parameterBecameConstInt(const int arg) { }";
+
+ # Parameter_Type ("int const" to int)
+ $HEADER1 .= "
+ $DECL_SPEC void parameterBecameNonConstInt(const int arg);";
+ $SOURCE1 .= "
+ void parameterBecameNonConstInt(const int arg) { }";
+
+ $HEADER2 .= "
+ $DECL_SPEC void parameterBecameNonConstInt(int arg);";
+ $SOURCE2 .= "
+ void parameterBecameNonConstInt(int arg) { }";
+
+ # Parameter_Became_Register
+ $HEADER1 .= "
+ $DECL_SPEC void parameterBecameRegister(int arg);";
+ $SOURCE1 .= "
+ void parameterBecameRegister(int arg) { }";
+
+ $HEADER2 .= "
+ $DECL_SPEC void parameterBecameRegister(register int arg);";
+ $SOURCE2 .= "
+ void parameterBecameRegister(register int arg) { }";
+
+ # Return_Type_Became_Const
+ $HEADER1 .= "
+ $DECL_SPEC char* returnTypeBecameConst(int param);";
+ $SOURCE1 .= "
+ char* returnTypeBecameConst(int param) { return (char*)malloc(256); }";
+
+ $HEADER2 .= "
+ $DECL_SPEC const char* returnTypeBecameConst(int param);";
+ $SOURCE2 .= "
+ const char* returnTypeBecameConst(int param) { return \"abc\"; }";
+
+ # Return_Type_Became_Const (2)
+ $HEADER1 .= "
+ $DECL_SPEC char* returnTypeBecameConst2(int param);";
+ $SOURCE1 .= "
+ char* returnTypeBecameConst2(int param) { return (char*)malloc(256); }";
+
+ $HEADER2 .= "
+ $DECL_SPEC char*const returnTypeBecameConst2(int param);";
+ $SOURCE2 .= "
+ char*const returnTypeBecameConst2(int param) { return (char*const)malloc(256); }";
+
+ # Return_Type_Became_Const (3)
+ $HEADER1 .= "
+ $DECL_SPEC char* returnTypeBecameConst3(int param);";
+ $SOURCE1 .= "
+ char* returnTypeBecameConst3(int param) { return (char*)malloc(256); }";
+
+ $HEADER2 .= "
+ $DECL_SPEC char const*const returnTypeBecameConst3(int param);";
+ $SOURCE2 .= "
+ char const*const returnTypeBecameConst3(int param) { return (char const*const)malloc(256); }";
+
+ # Added_Enum_Member
+ $HEADER1 .= "
+ enum AddedEnumMember {
+ OldMember
+ };
+ $DECL_SPEC int addedEnumMember(enum AddedEnumMember param);";
+ $SOURCE1 .= "
+ int addedEnumMember(enum AddedEnumMember param) { return 0; }";
+
+ $HEADER2 .= "
+ enum AddedEnumMember {
+ OldMember,
+ NewMember
+ };
+ $DECL_SPEC int addedEnumMember(enum AddedEnumMember param);";
+ $SOURCE2 .= "
+ int addedEnumMember(enum AddedEnumMember param) { return 0; }";
+
+ # Parameter_Type (Array)
+ $HEADER1 .= "
+ $DECL_SPEC int arrayParameterType(int param[5]);";
+ $SOURCE1 .= "
+ int arrayParameterType(int param[5]) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int arrayParameterType(int param[7]);";
+ $SOURCE2 .= "
+ int arrayParameterType(int param[7]) { return 0; }";
+
+ # Field_Type
+ $HEADER1 .= "
+ struct ArrayFieldType
+ {
+ int f;
+ int i[1];
+ };
+ $DECL_SPEC int arrayFieldType(struct ArrayFieldType param);";
+ $SOURCE1 .= "
+ int arrayFieldType(struct ArrayFieldType param) { return param.i[0]; }";
+
+ $HEADER2 .= "
+ struct ArrayFieldType
+ {
+ int f;
+ int i[];
+ };
+ $DECL_SPEC int arrayFieldType(struct ArrayFieldType param);";
+ $SOURCE2 .= "
+ int arrayFieldType(struct ArrayFieldType param) { return param.i[0]; }";
+
+ # Field_Type_And_Size (Array)
+ $HEADER1 .= "
+ struct ArrayFieldSize
+ {
+ int i[5];
+ };
+ $DECL_SPEC int arrayFieldSize(struct ArrayFieldSize param);";
+ $SOURCE1 .= "
+ int arrayFieldSize(struct ArrayFieldSize param) { return 0; }";
+
+ $HEADER2 .= "
+ struct ArrayFieldSize
+ {
+ int i[7];
+ };
+ $DECL_SPEC int arrayFieldSize(struct ArrayFieldSize param);";
+ $SOURCE2 .= "
+ int arrayFieldSize(struct ArrayFieldSize param) { return 0; }";
+
+ # Parameter_Became_NonVaList
+ $HEADER1 .= "
+ $DECL_SPEC int parameterNonVaList(int param, ...);";
+ $SOURCE1 .= "
+ int parameterNonVaList(int param, ...) { return param; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int parameterNonVaList(int param1, int param2);";
+ $SOURCE2 .= "
+ int parameterNonVaList(int param1, int param2) { return param1; }";
+
+ # Parameter_Became_VaList
+ $HEADER1 .= "
+ $DECL_SPEC int parameterVaList(int param1, int param2);";
+ $SOURCE1 .= "
+ int parameterVaList(int param1, int param2) { return param1; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int parameterVaList(int param, ...);";
+ $SOURCE2 .= "
+ int parameterVaList(int param, ...) { return param; }";
+
+ # Field_Type_And_Size
+ $HEADER1 .= "
+ struct FieldSizePadded
+ {
+ int i;
+ char changed_field;
+ // padding (3 bytes)
+ int j;
+ };
+ $DECL_SPEC int fieldSizePadded(struct FieldSizePadded param);";
+ $SOURCE1 .= "
+ int fieldSizePadded(struct FieldSizePadded param) { return 0; }";
+
+ $HEADER2 .= "
+ struct FieldSizePadded
+ {
+ int i;
+ int changed_field;
+ int j;
+ };
+ $DECL_SPEC int fieldSizePadded(struct FieldSizePadded param);";
+ $SOURCE2 .= "
+ int fieldSizePadded(struct FieldSizePadded param) { return 0; }";
+
+ # Parameter_Type_Format
+ $HEADER1 .= "
+ struct DType1
+ {
+ int i;
+ double j;
+ };
+ $DECL_SPEC int parameterTypeFormat(struct DType1 param);";
+ $SOURCE1 .= "
+ int parameterTypeFormat(struct DType1 param) { return 0; }";
+
+ $HEADER2 .= "
+ struct DType2
+ {
+ double i;
+ int j;
+ };
+ $DECL_SPEC int parameterTypeFormat(struct DType2 param);";
+ $SOURCE2 .= "
+ int parameterTypeFormat(struct DType2 param) { return 0; }";
+
+ # Parameter_Type_Format (struct to union)
+ $HEADER1 .= "
+ struct DType
+ {
+ int i;
+ double j;
+ };
+ $DECL_SPEC int parameterTypeFormat2(struct DType param);";
+ $SOURCE1 .= "
+ int parameterTypeFormat2(struct DType param) { return 0; }";
+
+ $HEADER2 .= "
+ union DType
+ {
+ int i;
+ long double j;
+ };
+ $DECL_SPEC int parameterTypeFormat2(union DType param);";
+ $SOURCE2 .= "
+ int parameterTypeFormat2(union DType param) { return 0; }";
+
+ # Global_Data_Size
+ $HEADER1 .= "
+ struct GlobalDataSize {
+ int a;
+ };
+ $EXTERN $DECL_SPEC struct GlobalDataSize globalDataSize;";
+
+ $HEADER2 .= "
+ struct GlobalDataSize {
+ int a, b;
+ };
+ $EXTERN $DECL_SPEC struct GlobalDataSize globalDataSize;";
+
+ # Global_Data_Type
+ $HEADER1 .= "
+ $EXTERN $DECL_SPEC int globalDataType;";
+
+ $HEADER2 .= "
+ $EXTERN $DECL_SPEC float globalDataType;";
+
+ # Global_Data_Type_And_Size
+ $HEADER1 .= "
+ $EXTERN $DECL_SPEC int globalDataTypeAndSize;";
+
+ $HEADER2 .= "
+ $EXTERN $DECL_SPEC short globalDataTypeAndSize;";
+
+ # Global_Data_Value (int)
+ $HEADER1 .= "
+ $EXTERN $DECL_SPEC const int globalDataValue = 10;";
+
+ $HEADER2 .= "
+ $EXTERN $DECL_SPEC const int globalDataValue = 15;";
+
+ # Global_Data_Became_Non_Const (int)
+ $HEADER1 .= "
+ $EXTERN $DECL_SPEC const int globalDataBecameNonConst = 10;";
+
+ $HEADER2 .= "
+ extern $DECL_SPEC int globalDataBecameNonConst;";
+ $SOURCE2 .= "
+ int globalDataBecameNonConst = 15;";
+
+ # Global_Data_Became_Const (safe)
+ $HEADER1 .= "
+ extern $DECL_SPEC int globalDataBecameConst;";
+ $SOURCE1 .= "
+ int globalDataBecameConst = 10;";
+
+ $HEADER2 .= "
+ $EXTERN $DECL_SPEC const int globalDataBecameConst=15;";
+
+ # Global_Data_Became_Non_Const (struct)
+ $HEADER1 .= "
+ struct GlobalDataType{int a;int b;struct GlobalDataType* p;};
+ $EXTERN $DECL_SPEC const struct GlobalDataType globalStructDataBecameConst = {1, 2, (struct GlobalDataType*)0};";
+
+ $HEADER2 .= "
+ struct GlobalDataType{int a;int b;struct GlobalDataType* p;};
+ $EXTERN $DECL_SPEC struct GlobalDataType globalStructDataBecameConst = {1, 2, (struct GlobalDataType*)0};";
+
+ # Removed_Parameter
+ $HEADER1 .= "
+ $DECL_SPEC int removedParameter(int param, int removed_param);";
+ $SOURCE1 .= "
+ int removedParameter(int param, int removed_param) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int removedParameter(int param);";
+ $SOURCE2 .= "
+ int removedParameter(int param) { return 0; }";
+
+ # Added_Parameter
+ $HEADER1 .= "
+ $DECL_SPEC int addedParameter(int param);";
+ $SOURCE1 .= "
+ int addedParameter(int param) { return param; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int addedParameter(int param, int added_param, int added_param2);";
+ $SOURCE2 .= "
+ int addedParameter(int param, int added_param, int added_param2) { return added_param2; }";
+
+ # Added_Interface (typedef to funcptr parameter)
+ $HEADER2 .= "
+ typedef int (*FUNCPTR_TYPE)(int a, int b);
+ $DECL_SPEC int addedFunc(FUNCPTR_TYPE*const** f);";
+ $SOURCE2 .= "
+ int addedFunc(FUNCPTR_TYPE*const** f) { return 0; }";
+
+ # Added_Interface (funcptr parameter)
+ $HEADER2 .= "
+ $DECL_SPEC int addedFunc2(int(*func)(int, int));";
+ $SOURCE2 .= "
+ int addedFunc2(int(*func)(int, int)) { return 0; }";
+
+ # Added_Interface (no limited parameters)
+ $HEADER2 .= "
+ $DECL_SPEC int addedFunc3(float p1, ...);";
+ $SOURCE2 .= "
+ int addedFunc3(float p1, ...) { return 0; }";
+
+ # Size
+ $HEADER1 .= "
+ struct TypeSize
+ {
+ long long i[5];
+ long j;
+ double k;
+ struct TypeSize* p;
+ };
+ $DECL_SPEC int testSize(struct TypeSize param, int param_2);";
+ $SOURCE1 .= "
+ int testSize(struct TypeSize param, int param_2) { return param_2; }";
+
+ $HEADER2 .= "
+ struct TypeSize
+ {
+ long long i[15];
+ long long j;
+ double k;
+ struct TypeSize* p;
+ };
+ $DECL_SPEC int testSize(struct TypeSize param, int param_2);";
+ $SOURCE2 .= "
+ int testSize(struct TypeSize param, int param_2) { return param_2; }";
+
+ # Added_Field_And_Size
+ $HEADER1 .= "
+ struct AddedFieldAndSize
+ {
+ int i;
+ long j;
+ double k;
+ struct AddedFieldAndSize* p;
+ };
+ $DECL_SPEC int addedFieldAndSize(struct AddedFieldAndSize param, int param_2);";
+ $SOURCE1 .= "
+ int addedFieldAndSize(struct AddedFieldAndSize param, int param_2) { return param_2; }";
+
+ $HEADER2 .= "
+ struct AddedFieldAndSize
+ {
+ int i;
+ long j;
+ double k;
+ struct AddedFieldAndSize* p;
+ int added_member1;
+ int added_member2;
+ };
+ $DECL_SPEC int addedFieldAndSize(struct AddedFieldAndSize param, int param_2);";
+ $SOURCE2 .= "
+ int addedFieldAndSize(struct AddedFieldAndSize param, int param_2) { return param_2; }";
+
+ # Added_Middle_Field_And_Size
+ $HEADER1 .= "
+ struct AddedMiddleFieldAndSize
+ {
+ int i;
+ long j;
+ double k;
+ struct AddedMiddleFieldAndSize* p;
+ };
+ $DECL_SPEC int addedMiddleFieldAndSize(struct AddedMiddleFieldAndSize param, int param_2);";
+ $SOURCE1 .= "
+ int addedMiddleFieldAndSize(struct AddedMiddleFieldAndSize param, int param_2) { return param_2; }";
+
+ $HEADER2 .= "
+ struct AddedMiddleFieldAndSize
+ {
+ int i;
+ int added_middle_member;
+ long j;
+ double k;
+ struct AddedMiddleFieldAndSize* p;
+ };
+ $DECL_SPEC int addedMiddleFieldAndSize(struct AddedMiddleFieldAndSize param, int param_2);";
+ $SOURCE2 .= "
+ int addedMiddleFieldAndSize(struct AddedMiddleFieldAndSize param, int param_2) { return param_2; }";
+
+ # Added_Middle_Field
+ $HEADER1 .= "
+ struct AddedMiddleField
+ {
+ unsigned char field1;
+ unsigned short field2;
+ };
+ $DECL_SPEC int addedMiddleField(struct AddedMiddleField param, int param_2);";
+ $SOURCE1 .= "
+ int addedMiddleField(struct AddedMiddleField param, int param_2) { return param_2; }";
+
+ $HEADER2 .= "
+ struct AddedMiddleField
+ {
+ unsigned char field1;
+ unsigned char added_field;
+ unsigned short field2;
+ };
+ $DECL_SPEC int addedMiddleField(struct AddedMiddleField param, int param_2);";
+ $SOURCE2 .= "
+ int addedMiddleField(struct AddedMiddleField param, int param_2) { return param_2; }";
+
+ # Renamed_Field
+ $HEADER1 .= "
+ struct RenamedField
+ {
+ long i;
+ long j;
+ double k;
+ struct RenamedField* p;
+ };
+ $DECL_SPEC int renamedField(struct RenamedField param, int param_2);";
+ $SOURCE1 .= "
+ int renamedField(struct RenamedField param, int param_2) { return param_2; }";
+
+ $HEADER2 .= "
+ struct RenamedField
+ {
+ long renamed_member;
+ long j;
+ double k;
+ struct RenamedField* p;
+ };
+ $DECL_SPEC int renamedField(struct RenamedField param, int param_2);";
+ $SOURCE2 .= "
+ int renamedField(struct RenamedField param, int param_2) { return param_2; }";
+
+ # Renamed_Field
+ $HEADER1 .= "
+ union RenamedUnionField
+ {
+ int renamed_from;
+ double j;
+ };
+ $DECL_SPEC int renamedUnionField(union RenamedUnionField param);";
+ $SOURCE1 .= "
+ int renamedUnionField(union RenamedUnionField param) { return 0; }";
+
+ $HEADER2 .= "
+ union RenamedUnionField
+ {
+ int renamed_to;
+ double j;
+ };
+ $DECL_SPEC int renamedUnionField(union RenamedUnionField param);";
+ $SOURCE2 .= "
+ int renamedUnionField(union RenamedUnionField param) { return 0; }";
+
+ # Removed_Field_And_Size
+ $HEADER1 .= "
+ struct RemovedFieldAndSize
+ {
+ int i;
+ long j;
+ double k;
+ struct RemovedFieldAndSize* p;
+ int removed_member1;
+ int removed_member2;
+ };
+ $DECL_SPEC int removedFieldAndSize(struct RemovedFieldAndSize param, int param_2);";
+ $SOURCE1 .= "
+ int removedFieldAndSize(struct RemovedFieldAndSize param, int param_2) { return param_2; }";
+
+ $HEADER2 .= "
+ struct RemovedFieldAndSize
+ {
+ int i;
+ long j;
+ double k;
+ struct RemovedFieldAndSize* p;
+ };
+ $DECL_SPEC int removedFieldAndSize(struct RemovedFieldAndSize param, int param_2);";
+ $SOURCE2 .= "
+ int removedFieldAndSize(struct RemovedFieldAndSize param, int param_2) { return param_2; }";
+
+ # Removed_Middle_Field
+ $HEADER1 .= "
+ struct RemovedMiddleField
+ {
+ int i;
+ int removed_middle_member;
+ long j;
+ double k;
+ struct RemovedMiddleField* p;
+ };
+ $DECL_SPEC int removedMiddleField(struct RemovedMiddleField param, int param_2);";
+ $SOURCE1 .= "
+ int removedMiddleField(struct RemovedMiddleField param, int param_2) { return param_2; }";
+
+ $HEADER2 .= "
+ struct RemovedMiddleField
+ {
+ int i;
+ long j;
+ double k;
+ struct RemovedMiddleField* p;
+ };
+ $DECL_SPEC int removedMiddleField(struct RemovedMiddleField param, int param_2);";
+ $SOURCE2 .= "
+ int removedMiddleField(struct RemovedMiddleField param, int param_2) { return param_2; }";
+
+ # Enum_Member_Value
+ $HEADER1 .= "
+ enum EnumMemberValue
+ {
+ MEMBER1=1,
+ MEMBER2=2
+ };
+ $DECL_SPEC int enumMemberValue(enum EnumMemberValue param);";
+ $SOURCE1 .= "
+ int enumMemberValue(enum EnumMemberValue param) { return 0; }";
+
+ $HEADER2 .= "
+ enum EnumMemberValue
+ {
+ MEMBER1=2,
+ MEMBER2=1
+ };
+ $DECL_SPEC int enumMemberValue(enum EnumMemberValue param);";
+ $SOURCE2 .= "
+ int enumMemberValue(enum EnumMemberValue param) { return 0; }";
+
+ # Enum_Member_Removed
+ $HEADER1 .= "
+ enum EnumMemberRemoved
+ {
+ MEMBER=1,
+ MEMBER_REMOVED=2
+ };
+ $DECL_SPEC int enumMemberRemoved(enum EnumMemberRemoved param);";
+ $SOURCE1 .= "
+ int enumMemberRemoved(enum EnumMemberRemoved param) { return 0; }";
+
+ $HEADER2 .= "
+ enum EnumMemberRemoved
+ {
+ MEMBER=1
+ };
+ $DECL_SPEC int enumMemberRemoved(enum EnumMemberRemoved param);";
+ $SOURCE2 .= "
+ int enumMemberRemoved(enum EnumMemberRemoved param) { return 0; }";
+
+ # Enum_Member_Removed (middle)
+ $HEADER1 .= "
+ enum EnumMiddleMemberRemoved
+ {
+ MEM_REMOVED,
+ MEM1,
+ MEM2
+ };
+ $DECL_SPEC int enumMiddleMemberRemoved(enum EnumMiddleMemberRemoved param);";
+ $SOURCE1 .= "
+ int enumMiddleMemberRemoved(enum EnumMiddleMemberRemoved param) { return 0; }";
+
+ $HEADER2 .= "
+ enum EnumMiddleMemberRemoved
+ {
+ MEM1,
+ MEM2
+ };
+ $DECL_SPEC int enumMiddleMemberRemoved(enum EnumMiddleMemberRemoved param);";
+ $SOURCE2 .= "
+ int enumMiddleMemberRemoved(enum EnumMiddleMemberRemoved param) { return 0; }";
+
+ # Enum_Member_Name
+ $HEADER1 .= "
+ enum EnumMemberName
+ {
+ BRANCH1=1,
+ BRANCH2=2
+ };
+ $DECL_SPEC int enumMemberName(enum EnumMemberName param);";
+ $SOURCE1 .= "
+ int enumMemberName(enum EnumMemberName param) { return 0; }";
+
+ $HEADER2 .= "
+ enum EnumMemberName
+ {
+ BRANCH_FIRST=1,
+ BRANCH_SECOND=2
+ };
+ $DECL_SPEC int enumMemberName(enum EnumMemberName param);";
+ $SOURCE2 .= "
+ int enumMemberName(enum EnumMemberName param) { return 0; }";
+
+ # Field_Type_And_Size
+ $HEADER1 .= "
+ struct FieldTypeAndSize
+ {
+ int i;
+ long j;
+ double k;
+ struct FieldTypeAndSize* p;
+ };
+ $DECL_SPEC int fieldTypeAndSize(struct FieldTypeAndSize param, int param_2);";
+ $SOURCE1 .= "
+ int fieldTypeAndSize(struct FieldTypeAndSize param, int param_2) { return param_2; }";
+
+ $HEADER2 .= "
+ struct FieldTypeAndSize
+ {
+ int i;
+ long long j;
+ double k;
+ struct FieldTypeAndSize* p;
+ };
+ $DECL_SPEC int fieldTypeAndSize(struct FieldTypeAndSize param, int param_2);";
+ $SOURCE2 .= "
+ int fieldTypeAndSize(struct FieldTypeAndSize param, int param_2) { return param_2; }";
+
+ # Field_Type
+ $HEADER1 .= "
+ struct FieldType
+ {
+ int i;
+ long j;
+ double k;
+ struct FieldType* p;
+ };
+ $DECL_SPEC int fieldType(struct FieldType param, int param_2);";
+ $SOURCE1 .= "
+ int fieldType(struct FieldType param, int param_2) { return param_2; }";
+
+ $HEADER2 .= "
+ struct FieldType
+ {
+ float i;
+ long j;
+ double k;
+ struct FieldType* p;
+ };
+ $DECL_SPEC int fieldType(struct FieldType param, int param_2);";
+ $SOURCE2 .= "
+ int fieldType(struct FieldType param, int param_2) { return param_2; }";
+
+ # Field_BaseType
+ $HEADER1 .= "
+ struct FieldBaseType
+ {
+ int i;
+ long *j;
+ double k;
+ struct FieldBaseType* p;
+ };
+ $DECL_SPEC int fieldBaseType(struct FieldBaseType param, int param_2);";
+ $SOURCE1 .= "
+ int fieldBaseType(struct FieldBaseType param, int param_2) { return param_2; }";
+
+ $HEADER2 .= "
+ struct FieldBaseType
+ {
+ int i;
+ long long *j;
+ double k;
+ struct FieldBaseType* p;
+ };
+ $DECL_SPEC int fieldBaseType(struct FieldBaseType param, int param_2);";
+ $SOURCE2 .= "
+ int fieldBaseType(struct FieldBaseType param, int param_2) { return param_2; }";
+
+ # Field_PointerLevel (and Size)
+ $HEADER1 .= "
+ struct FieldPointerLevelAndSize
+ {
+ int i;
+ long long j;
+ double k;
+ struct FieldPointerLevelAndSize* p;
+ };
+ $DECL_SPEC int fieldPointerLevelAndSize(struct FieldPointerLevelAndSize param, int param_2);";
+ $SOURCE1 .= "
+ int fieldPointerLevelAndSize(struct FieldPointerLevelAndSize param, int param_2) { return param_2; }";
+
+ $HEADER2 .= "
+ struct FieldPointerLevelAndSize
+ {
+ int i;
+ long long *j;
+ double k;
+ struct FieldPointerLevelAndSize* p;
+ };
+ $DECL_SPEC int fieldPointerLevelAndSize(struct FieldPointerLevelAndSize param, int param_2);";
+ $SOURCE2 .= "
+ int fieldPointerLevelAndSize(struct FieldPointerLevelAndSize param, int param_2) { return param_2; }";
+
+ # Field_PointerLevel
+ $HEADER1 .= "
+ struct FieldPointerLevel
+ {
+ int i;
+ long *j;
+ double k;
+ struct FieldPointerLevel* p;
+ };
+ $DECL_SPEC int fieldPointerLevel(struct FieldPointerLevel param, int param_2);";
+ $SOURCE1 .= "
+ int fieldPointerLevel(struct FieldPointerLevel param, int param_2) { return param_2; }";
+
+ $HEADER2 .= "
+ struct FieldPointerLevel
+ {
+ int i;
+ long **j;
+ double k;
+ struct FieldPointerLevel* p;
+ };
+ $DECL_SPEC int fieldPointerLevel(struct FieldPointerLevel param, int param_2);";
+ $SOURCE2 .= "
+ int fieldPointerLevel(struct FieldPointerLevel param, int param_2) { return param_2; }";
+
+ # Added_Interface
+ $HEADER2 .= "
+ $DECL_SPEC int addedFunc4(int param);";
+ $SOURCE2 .= "
+ int addedFunc4(int param) { return param; }";
+
+ # Removed_Interface
+ $HEADER1 .= "
+ $DECL_SPEC int removedFunc(int param);";
+ $SOURCE1 .= "
+ int removedFunc(int param) { return param; }";
+
+ # Parameter_Type_And_Size
+ $HEADER1 .= "
+ $DECL_SPEC int parameterTypeAndSize(int param, int other_param);";
+ $SOURCE1 .= "
+ int parameterTypeAndSize(int param, int other_param) { return other_param; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int parameterTypeAndSize(long long param, int other_param);";
+ $SOURCE2 .= "
+ int parameterTypeAndSize(long long param, int other_param) { return other_param; }";
+
+ # Parameter_Type_And_Size (test calling conventions)
+ $HEADER1 .= "\n
+ $DECL_SPEC int parameterCallingConvention(int p1, int p2, int p3);";
+ $SOURCE1 .= "
+ int parameterCallingConvention(int p1, int p2, int p3) { return 0; }";
+
+ $HEADER2 .= "\n
+ $DECL_SPEC float parameterCallingConvention(char p1, int p2, int p3);";
+ $SOURCE2 .= "
+ float parameterCallingConvention(char p1, int p2, int p3) { return 7.0f; }";
+
+ # Parameter_Type
+ $HEADER1 .= "
+ $DECL_SPEC int parameterType(int param, int other_param);";
+ $SOURCE1 .= "
+ int parameterType(int param, int other_param) { return other_param; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int parameterType(float param, int other_param);";
+ $SOURCE2 .= "
+ int parameterType(float param, int other_param) { return other_param; }";
+
+ # Parameter_Became_Non_Const
+ $HEADER1 .= "
+ $DECL_SPEC int parameterBecameNonConst(int const* param);";
+ $SOURCE1 .= "
+ int parameterBecameNonConst(int const* param) { return *param; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int parameterBecameNonConst(int* param);";
+ $SOURCE2 .= "
+ int parameterBecameNonConst(int* param) {
+ *param=10;
+ return *param;
+ }";
+
+ # Parameter_BaseType (Typedef)
+ $HEADER1 .= "
+ typedef int* PARAM_TYPEDEF;
+ $DECL_SPEC int parameterBaseTypedefChange(PARAM_TYPEDEF param);";
+ $SOURCE1 .= "
+ int parameterBaseTypedefChange(PARAM_TYPEDEF param) { return 0; }";
+
+ $HEADER2 .= "
+ typedef const int* PARAM_TYPEDEF;
+ $DECL_SPEC int parameterBaseTypedefChange(PARAM_TYPEDEF param);";
+ $SOURCE2 .= "
+ int parameterBaseTypedefChange(PARAM_TYPEDEF param) { return 0; }";
+
+ # Parameter_BaseType
+ $HEADER1 .= "
+ $DECL_SPEC int parameterBaseTypeChange(int *param);";
+ $SOURCE1 .= "
+ int parameterBaseTypeChange(int *param) { return sizeof(*param); }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int parameterBaseTypeChange(long long *param);";
+ $SOURCE2 .= "
+ int parameterBaseTypeChange(long long *param) { return sizeof(*param); }";
+
+ # Parameter_PointerLevel
+ $HEADER1 .= "
+ $DECL_SPEC long long parameterPointerLevelAndSize(long long param);";
+ $SOURCE1 .= "
+ long long parameterPointerLevelAndSize(long long param) { return param; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC long long parameterPointerLevelAndSize(long long *param);";
+ $SOURCE2 .= "
+ long long parameterPointerLevelAndSize(long long *param) { return param[5]; }";
+
+ # Parameter_PointerLevel
+ $HEADER1 .= "
+ $DECL_SPEC int parameterPointerLevel(int *param);";
+ $SOURCE1 .= "
+ int parameterPointerLevel(int *param) { return param[5]; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int parameterPointerLevel(int **param);";
+ $SOURCE2 .= "
+ int parameterPointerLevel(int **param) { return param[5][5]; }";
+
+ # Return_Type_And_Size
+ $HEADER1 .= "
+ $DECL_SPEC int returnTypeAndSize(int param);";
+ $SOURCE1 .= "
+ int returnTypeAndSize(int param) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC long long returnTypeAndSize(int param);";
+ $SOURCE2 .= "
+ long long returnTypeAndSize(int param) { return 0; }";
+
+ # Return_Type
+ $HEADER1 .= "
+ $DECL_SPEC int returnType(int param);";
+ $SOURCE1 .= "
+ int returnType(int param) { return 1; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC float returnType(int param);";
+ $SOURCE2 .= "
+ float returnType(int param) { return 1; }";
+
+ # Return_Type_Became_Void ("int" to "void")
+ $HEADER1 .= "
+ $DECL_SPEC int returnTypeChangeToVoid(int param);";
+ $SOURCE1 .= "
+ int returnTypeChangeToVoid(int param) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC void returnTypeChangeToVoid(int param);";
+ $SOURCE2 .= "
+ void returnTypeChangeToVoid(int param) { return; }";
+
+ # Return_Type ("struct" to "void*")
+ $HEADER1 .= "
+ struct SomeStruct {int A;long B;};
+ $DECL_SPEC struct SomeStruct* returnTypeChangeToVoidPtr(int param);";
+ $SOURCE1 .= "
+ struct SomeStruct* returnTypeChangeToVoidPtr(int param) { return (struct SomeStruct*)0; }";
+
+ $HEADER2 .= "
+ struct SomeStruct {int A;int B;};
+ $DECL_SPEC void* returnTypeChangeToVoidPtr(int param);";
+ $SOURCE2 .= "
+ void* returnTypeChangeToVoidPtr(int param) { return (void*)0; }";
+
+ # Return_Type_From_Void_And_Stack_Layout ("void" to "struct")
+ $HEADER1 .= "
+ $DECL_SPEC void returnTypeChangeFromVoidToStruct(int param);";
+ $SOURCE1 .= "
+ void returnTypeChangeFromVoidToStruct(int param) { return; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC struct SomeStruct returnTypeChangeFromVoidToStruct(int param);";
+ $SOURCE2 .= "
+ struct SomeStruct returnTypeChangeFromVoidToStruct(int param) {
+ struct SomeStruct obj = {1,2};
+ return obj;
+ }";
+
+ # Return_Type_Became_Void_And_Stack_Layout ("struct" to "void")
+ $HEADER1 .= "
+ $DECL_SPEC struct SomeStruct returnTypeChangeFromStructToVoid(int param);";
+ $SOURCE1 .= "
+ struct SomeStruct returnTypeChangeFromStructToVoid(int param) {
+ struct SomeStruct obj = {1,2};
+ return obj;
+ }";
+
+ $HEADER2 .= "
+ $DECL_SPEC void returnTypeChangeFromStructToVoid(int param);";
+ $SOURCE2 .= "
+ void returnTypeChangeFromStructToVoid(int param) { return; }";
+
+ # Return_Type_From_Void_And_Stack_Layout (safe, "void" to "long")
+ $HEADER1 .= "
+ $DECL_SPEC void returnTypeChangeFromVoidToLong(int param);";
+ $SOURCE1 .= "
+ void returnTypeChangeFromVoidToLong(int param) { return; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC long returnTypeChangeFromVoidToLong(int param);";
+ $SOURCE2 .= "
+ long returnTypeChangeFromVoidToLong(int param) { return 0; }";
+
+ # Return_Type_From_Register_To_Stack ("int" to "struct")
+ $HEADER1 .= "
+ $DECL_SPEC int returnTypeChangeFromIntToStruct(int param);";
+ $SOURCE1 .= "
+ int returnTypeChangeFromIntToStruct(int param) { return param; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC struct SomeStruct returnTypeChangeFromIntToStruct(int param);";
+ $SOURCE2 .= "
+ struct SomeStruct returnTypeChangeFromIntToStruct(int param) {
+ struct SomeStruct obj = {1,2};
+ return obj;
+ }";
+
+ # Return_Type_From_Stack_To_Register (from struct to int)
+ $HEADER1 .= "
+ $DECL_SPEC struct SomeStruct returnTypeChangeFromStructToInt(int param);";
+ $SOURCE1 .= "
+ struct SomeStruct returnTypeChangeFromStructToInt(int param) {
+ struct SomeStruct obj = {1,2};
+ return obj;
+ }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int returnTypeChangeFromStructToInt(int param);";
+ $SOURCE2 .= "
+ int returnTypeChangeFromStructToInt(int param) { return param; }";
+
+ # Return_Type_From_Stack_To_Register (from struct to int, without parameters)
+ $HEADER1 .= "
+ $DECL_SPEC struct SomeStruct returnTypeChangeFromStructToIntWithNoParams();";
+ $SOURCE1 .= "
+ struct SomeStruct returnTypeChangeFromStructToIntWithNoParams() {
+ struct SomeStruct obj = {1,2};
+ return obj;
+ }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int returnTypeChangeFromStructToIntWithNoParams();";
+ $SOURCE2 .= "
+ int returnTypeChangeFromStructToIntWithNoParams() { return 0; }";
+
+ # Return_BaseType
+ $HEADER1 .= "
+ $DECL_SPEC int *returnBaseTypeChange(int param);";
+ $SOURCE1 .= "
+ int *returnBaseTypeChange(int param) { return (int*)0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC long long *returnBaseTypeChange(int param);";
+ $SOURCE2 .= "
+ long long *returnBaseTypeChange(int param) { return (long long*)0; }";
+
+ # Return_PointerLevel
+ $HEADER1 .= "
+ $DECL_SPEC long long returnPointerLevelAndSize(int param);";
+ $SOURCE1 .= "
+ long long returnPointerLevelAndSize(int param) { return 100; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC long long *returnPointerLevelAndSize(int param);";
+ $SOURCE2 .= "
+ long long *returnPointerLevelAndSize(int param) { return (long long *)0; }";
+
+ # Return_PointerLevel
+ $HEADER1 .= "
+ $DECL_SPEC long long *returnPointerLevel(int param);";
+ $SOURCE1 .= "
+ long long *returnPointerLevel(int param) { return (long long *)0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC long long **returnPointerLevel(int param);";
+ $SOURCE2 .= "
+ long long **returnPointerLevel(int param) { return (long long **)0; }";
+
+ # Size (typedef to anon structure)
+ $HEADER1 .= "
+ typedef struct
+ {
+ int i;
+ long j;
+ double k;
+ } AnonTypedef;
+ $DECL_SPEC int anonTypedef(AnonTypedef param);";
+ $SOURCE1 .= "
+ int anonTypedef(AnonTypedef param) { return 0; }";
+
+ $HEADER2 .= "
+ typedef struct
+ {
+ int i;
+ long j;
+ double k;
+ union {
+ int dummy[256];
+ struct {
+ char q_skiptable[256];
+ const char *p;
+ int l;
+ } p;
+ };
+ } AnonTypedef;
+ $DECL_SPEC int anonTypedef(AnonTypedef param);";
+ $SOURCE2 .= "
+ int anonTypedef(AnonTypedef param) { return 0; }";
+
+ # Size (safe: opaque)
+ $HEADER1 .= "
+ struct OpaqueType
+ {
+ long long i[5];
+ long j;
+ double k;
+ struct OpaqueType* p;
+ };
+ $DECL_SPEC int opaqueTypeUse(struct OpaqueType param, int param_2);";
+ $SOURCE1 .= "
+ int opaqueTypeUse(struct OpaqueType param, int param_2) { return param_2; }";
+
+ $HEADER2 .= "
+ struct OpaqueType
+ {
+ long long i[5];
+ long long j;
+ double k;
+ struct OpaqueType* p;
+ };
+ $DECL_SPEC int opaqueTypeUse(struct OpaqueType param, int param_2);";
+ $SOURCE2 .= "
+ int opaqueTypeUse(struct OpaqueType param, int param_2) { return param_2; }";
+
+ # Size (safe: internal)
+ $HEADER1 .= "
+ struct InternalType
+ {
+ long long i[5];
+ long j;
+ double k;
+ struct InternalType* p;
+ };
+ $DECL_SPEC int internalTypeUse(struct InternalType param, int param_2);";
+ $SOURCE1 .= "
+ int internalTypeUse(struct InternalType param, int param_2) { return param_2; }";
+
+ $HEADER2 .= "
+ struct InternalType
+ {
+ long long i[5];
+ long long j;
+ double k;
+ struct InternalType* p;
+ };
+ $DECL_SPEC int internalTypeUse(struct InternalType param, int param_2);";
+ $SOURCE2 .= "
+ int internalTypeUse(struct InternalType param, int param_2) { return param_2; }";
+
+ if($OSgroup eq "linux")
+ {
+ # Changed version
+ $HEADER1 .= "
+ $DECL_SPEC int changedVersion(int param);
+ $DECL_SPEC int changedDefaultVersion(int param);";
+ $SOURCE1 .= "
+ int changedVersion(int param) { return 0; }
+ __asm__(\".symver changedVersion,changedVersion\@VERSION_2.0\");
+ int changedDefaultVersion(int param) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int changedVersion(int param);
+ $DECL_SPEC int changedDefaultVersion(long param);";
+ $SOURCE2 .= "
+ int changedVersion(int param) { return 0; }
+ __asm__(\".symver changedVersion,changedVersion\@VERSION_3.0\");
+ int changedDefaultVersion(long param) { return 0; }";
+
+ # Unchanged version
+ $HEADER1 .= "
+ $DECL_SPEC int unchangedVersion(int param);
+ $DECL_SPEC int unchangedDefaultVersion(int param);";
+ $SOURCE1 .= "
+ int unchangedVersion(int param) { return 0; }
+ __asm__(\".symver unchangedVersion,unchangedVersion\@VERSION_1.0\");
+ int unchangedDefaultVersion(int param) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int unchangedVersion(int param);
+ $DECL_SPEC int unchangedDefaultVersion(int param);";
+ $SOURCE2 .= "
+ int unchangedVersion(int param) { return 0; }
+ __asm__(\".symver unchangedVersion,unchangedVersion\@VERSION_1.0\");
+ int unchangedDefaultVersion(int param) { return 0; }";
+
+ # Non-Default to Default
+ $HEADER1 .= "
+ $DECL_SPEC int changedVersionToDefault(int param);";
+ $SOURCE1 .= "
+ int changedVersionToDefault(int param) { return 0; }
+ __asm__(\".symver changedVersionToDefault,changedVersionToDefault\@VERSION_1.0\");";
+
+ $HEADER2 .= "
+ $DECL_SPEC int changedVersionToDefault(long param);";
+ $SOURCE2 .= "
+ int changedVersionToDefault(long param) { return 0; }";
+
+ # Default to Non-Default
+ $HEADER1 .= "
+ $DECL_SPEC int changedVersionToNonDefault(int param);";
+ $SOURCE1 .= "
+ int changedVersionToNonDefault(int param) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int changedVersionToNonDefault(long param);";
+ $SOURCE2 .= "
+ int changedVersionToNonDefault(long param) { return 0; }
+ __asm__(\".symver changedVersionToNonDefault,changedVersionToNonDefault\@VERSION_3.0\");";
+
+ # Added version
+ $HEADER1 .= "
+ $DECL_SPEC int addedVersion(int param);
+ $DECL_SPEC int addedDefaultVersion(int param);";
+ $SOURCE1 .= "
+ int addedVersion(int param) { return 0; }
+ int addedDefaultVersion(int param) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int addedVersion(int param);
+ $DECL_SPEC int addedDefaultVersion(int param);";
+ $SOURCE2 .= "
+ int addedVersion(int param) { return 0; }
+ __asm__(\".symver addedVersion,addedVersion\@VERSION_2.0\");
+ int addedDefaultVersion(int param) { return 0; }";
+
+ # Removed version
+ $HEADER1 .= "
+ $DECL_SPEC int removedVersion(int param);
+ $DECL_SPEC int removedVersion2(int param);
+ $DECL_SPEC int removedDefaultVersion(int param);";
+ $SOURCE1 .= "
+ int removedVersion(int param) { return 0; }
+ __asm__(\".symver removedVersion,removedVersion\@VERSION_1.0\");
+ int removedVersion2(int param) { return 0; }
+ __asm__(\".symver removedVersion2,removedVersion\@VERSION_3.0\");
+ int removedDefaultVersion(int param) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int removedVersion(int param);
+ $DECL_SPEC int removedVersion2(int param);
+ $DECL_SPEC int removedDefaultVersion(int param);";
+ $SOURCE2 .= "
+ int removedVersion(int param) { return 0; }
+ int removedVersion2(int param) { return 0; }
+ __asm__(\".symver removedVersion2,removedVersion\@VERSION_3.0\");
+ int removedDefaultVersion(int param) { return 0; }";
+
+ # Return_Type (good versioning)
+ $HEADER1 .= "
+ $DECL_SPEC int goodVersioning(int param);";
+ $SOURCE1 .= "
+ int goodVersioning(int param) { return 0; }
+ __asm__(\".symver goodVersioning,goodVersioning\@VERSION_1.0\");";
+
+ $HEADER2 .= "
+ $DECL_SPEC int goodVersioningOld(int param);";
+ $SOURCE2 .= "
+ int goodVersioningOld(int param) { return 0; }
+ __asm__(\".symver goodVersioningOld,goodVersioning\@VERSION_1.0\");";
+
+ $HEADER2 .= "
+ $DECL_SPEC float goodVersioning(int param);";
+ $SOURCE2 .= "
+ float goodVersioning(int param) { return 0.7; }
+ __asm__(\".symver goodVersioning,goodVersioning\@VERSION_2.0\");";
+
+ # Return_Type (bad versioning)
+ $HEADER1 .= "
+ $DECL_SPEC int badVersioning(int param);";
+ $SOURCE1 .= "
+ int badVersioning(int param) { return 0; }
+ __asm__(\".symver badVersioning,badVersioning\@VERSION_1.0\");";
+
+ $HEADER2 .= "
+ $DECL_SPEC float badVersioningOld(int param);";
+ $SOURCE2 .= "
+ float badVersioningOld(int param) { return 0.7; }
+ __asm__(\".symver badVersioningOld,badVersioning\@VERSION_1.0\");";
+
+ $HEADER2 .= "
+ $DECL_SPEC float badVersioning(int param);";
+ $SOURCE2 .= "
+ float badVersioning(int param) { return 0.7; }
+ __asm__(\".symver badVersioning,badVersioning\@VERSION_2.0\");";
+ }
+ # unnamed struct/union fields within structs/unions
+ $HEADER1 .= "
+ typedef struct
+ {
+ int a;
+ union {
+ int b;
+ float c;
+ };
+ int d;
+ } UnnamedTypeSize;
+ $DECL_SPEC int unnamedTypeSize(UnnamedTypeSize param);";
+ $SOURCE1 .= "
+ int unnamedTypeSize(UnnamedTypeSize param) { return 0; }";
+
+ $HEADER2 .= "
+ typedef struct
+ {
+ int a;
+ union {
+ long double b;
+ float c;
+ };
+ int d;
+ } UnnamedTypeSize;
+ $DECL_SPEC int unnamedTypeSize(UnnamedTypeSize param);";
+ $SOURCE2 .= "
+ int unnamedTypeSize(UnnamedTypeSize param) { return 0; }";
+
+ # Changed_Constant
+ $HEADER1 .= "
+ #define PUBLIC_CONSTANT \"old_value\"";
+ $HEADER2 .= "
+ #define PUBLIC_CONSTANT \"new_value\"";
+
+ # Changed_Constant (Safe)
+ $HEADER1 .= "
+ #define INTEGER_CONSTANT 0x01";
+ $HEADER2 .= "
+ #define INTEGER_CONSTANT 1";
+
+ # Changed_Constant (Safe)
+ $HEADER1 .= "
+ #define PRIVATE_CONSTANT \"old_value\"
+ #undef PRIVATE_CONSTANT";
+ $HEADER2 .= "
+ #define PRIVATE_CONSTANT \"new_value\"
+ #undef PRIVATE_CONSTANT";
+
+ # Added_Field (union)
+ $HEADER1 .= "
+ union UnionTypeAddedField
+ {
+ int a;
+ struct {
+ int b;
+ float c;
+ };
+ int d;
+ };
+ $DECL_SPEC int unionTypeAddedField(union UnionTypeAddedField param);";
+ $SOURCE1 .= "
+ int unionTypeAddedField(union UnionTypeAddedField param) { return 0; }";
+
+ $HEADER2 .= "
+ union UnionTypeAddedField
+ {
+ int a;
+ struct {
+ long double x, y;
+ } new_field;
+ struct {
+ int b;
+ float c;
+ };
+ int d;
+ };
+ $DECL_SPEC int unionTypeAddedField(union UnionTypeAddedField param);";
+ $SOURCE2 .= "
+ int unionTypeAddedField(union UnionTypeAddedField param) { return 0; }";
+
+ # Prameter_BaseType (typedef)
+ $HEADER1 .= "
+ typedef float TYPEDEF_TYPE;
+ $DECL_SPEC int parameterTypedefChange(TYPEDEF_TYPE param);";
+ $SOURCE1 .= "
+ int parameterTypedefChange(TYPEDEF_TYPE param) { return 1.0; }";
+
+ $HEADER2 .= "
+ typedef int TYPEDEF_TYPE;
+ $DECL_SPEC int parameterTypedefChange(TYPEDEF_TYPE param);";
+ $SOURCE2 .= "
+ int parameterTypedefChange(TYPEDEF_TYPE param) { return 1; }";
+
+ # Field_BaseType (typedef in member type)
+ $HEADER1 .= "
+ typedef float TYPEDEF_TYPE_2;
+ struct FieldBaseTypedefChange {
+ TYPEDEF_TYPE_2 m;
+ };
+ $DECL_SPEC int fieldBaseTypedefChange(struct FieldBaseTypedefChange param);";
+ $SOURCE1 .= "
+ int fieldBaseTypedefChange(struct FieldBaseTypedefChange param) { return 1; }";
+
+ $HEADER2 .= "
+ typedef int TYPEDEF_TYPE_2;
+ struct FieldBaseTypedefChange {
+ TYPEDEF_TYPE_2 m;
+ };
+ $DECL_SPEC int fieldBaseTypedefChange(struct FieldBaseTypedefChange param);";
+ $SOURCE2 .= "
+ int fieldBaseTypedefChange(struct FieldBaseTypedefChange param) { return 1; }";
+
+ # C++ keywords in C code
+ $HEADER1 .= "
+ $DECL_SPEC int testCppKeywords1(int class, int virtual, int (*new)(int));";
+ $SOURCE1 .= "
+ $DECL_SPEC int testCppKeywords1(int class, int virtual, int (*new)(int)) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int testCppKeywords1(int class, int virtual);
+ $DECL_SPEC int testCppKeywords2(int operator, int other);
+ $DECL_SPEC int testCppKeywords3(int operator);
+ $DECL_SPEC int operator(int class, int this);
+ $DECL_SPEC int delete(int virtual, int* this);
+ struct CppKeywords {
+ int bool: 8;
+ //int*this;
+ };
+ #ifdef __cplusplus
+ class TestCppKeywords {
+ void operator delete(void*);
+ void operator ()(int);
+ void operator,(int);
+ void delete() {
+ delete this;
+ };
+ };
+ #endif";
+ $SOURCE2 .= "
+ $DECL_SPEC int testCppKeywords(int class, int virtual) { return 0; }";
+
+ # Regression
+ $HEADER1 .= "
+ $DECL_SPEC int* testRegression(int *pointer, char const *name, ...);";
+ $SOURCE1 .= "
+ int* testRegression(int *pointer, char const *name, ...) { return 0; }";
+
+ $HEADER2 .= "
+ $DECL_SPEC int* testRegression(int *pointer, char const *name, ...);";
+ $SOURCE2 .= "
+ int* testRegression(int *pointer, char const *name, ...) { return 0; }";
+
+ runTests("libsample_c", "C", $HEADER1, $SOURCE1, $HEADER2, $SOURCE2, "OpaqueType", "internalTypeUse");
+}
+
+sub runTests($$$$$$$$)
+{
+ my ($LibName, $Lang, $HEADER1, $SOURCE1, $HEADER2, $SOURCE2, $Opaque, $Private) = @_;
+ my $Ext = ($Lang eq "C++")?"cpp":"c";
+ rmtree($LibName);
+ # creating test suite
+ my $Path_v1 = "$LibName/libsample.v1";
+ my $Path_v2 = "$LibName/libsample.v2";
+ mkpath($Path_v1);
+ mkpath($Path_v2);
+ writeFile("$Path_v1/libsample.h", $HEADER1."\n");
+ writeFile("$Path_v1/libsample.$Ext", "#include \"libsample.h\"\n".$SOURCE1."\n");
+ writeFile("$LibName/v1.xml", "
+ <version>
+ 1.0
+ </version>
+
+ <headers>
+ ".get_abs_path($Path_v1)."
+ </headers>
+
+ <libs>
+ ".get_abs_path($Path_v1)."
+ </libs>
+
+ <skip_types>
+ $Opaque
+ </skip_types>
+
+ <skip_symbols>
+ $Private
+ </skip_symbols>
+
+ <include_paths>
+ ".get_abs_path($Path_v1)."
+ </include_paths>\n");
+ writeFile("$Path_v1/test.$Ext", "
+ #include \"libsample.h\"
+ #include <stdio.h>
+ ".($Lang eq "C++"?"using namespace TestNS;":"")."
+ int main()
+ {
+ int ret = 0;
+ printf(\"\%d\\n\", ret);
+ return 0;
+ }\n");
+
+ writeFile("$Path_v2/libsample.h", $HEADER2."\n");
+ writeFile("$Path_v2/libsample.$Ext", "#include \"libsample.h\"\n".$SOURCE2."\n");
+ writeFile("$LibName/v2.xml", "
+ <version>
+ 2.0
+ </version>
+
+ <headers>
+ ".get_abs_path($Path_v2)."
+ </headers>
+
+ <libs>
+ ".get_abs_path($Path_v2)."
+ </libs>
+
+ <skip_types>
+ $Opaque
+ </skip_types>
+
+ <skip_symbols>
+ $Private
+ </skip_symbols>
+
+ <include_paths>
+ ".get_abs_path($Path_v2)."
+ </include_paths>\n");
+ writeFile("$Path_v2/test.$Ext", "
+ #include \"libsample.h\"
+ #include <stdio.h>
+ ".($Lang eq "C++"?"using namespace TestNS;":"")."
+ int main()
+ {
+ int ret = 0;
+ printf(\"\%d\\n\", ret);
+ return 0;
+ }\n");
+
+ my ($BuildCmd, $BuildCmd_Test) = ("", "");
+ if($OSgroup eq "windows")
+ {
+ check_win32_env(); # to run MS VC++ compiler
+ my $CL = get_CmdPath("cl");
+ if(not $CL) {
+ exitStatus("Not_Found", "can't find \"cl\" compiler");
+ }
+ $BuildCmd = "$CL /LD libsample.$Ext >build_log.txt 2>&1";
+ $BuildCmd_Test = "$CL test.$Ext libsample.$LIB_EXT";
+ }
+ elsif($OSgroup eq "linux")
+ {
+ if($Lang eq "C")
+ { # tests for symbol versioning
+ writeFile("$Path_v1/version", "
+ VERSION_1.0 {
+ unchangedDefaultVersion;
+ removedDefaultVersion;
+ };
+ VERSION_2.0 {
+ changedDefaultVersion;
+ };
+ VERSION_3.0 {
+ changedVersionToNonDefault;
+ };
+ ");
+ writeFile("$Path_v2/version", "
+ VERSION_1.0 {
+ unchangedDefaultVersion;
+ changedVersionToDefault;
+ };
+ VERSION_2.0 {
+ addedDefaultVersion;
+ };
+ VERSION_3.0 {
+ changedDefaultVersion;
+ };
+ ");
+ $BuildCmd = $GCC_PATH." -Wl,--version-script version -shared -fkeep-inline-functions libsample.$Ext -o libsample.$LIB_EXT";
+ $BuildCmd_Test = $GCC_PATH." -Wl,--version-script version test.$Ext -Wl,libsample.$LIB_EXT -o test";
+ }
+ else
+ {
+ $BuildCmd = $GCC_PATH." -shared -fkeep-inline-functions -x c++ libsample.$Ext -lstdc++ -o libsample.$LIB_EXT";
+ $BuildCmd_Test = $GCC_PATH." -x c++ test.$Ext -lstdc++ -Wl,libsample.$LIB_EXT -o test";
+ }
+ if(getArch(1)=~/\A(arm|x86_64)\Z/i)
+ { # relocation R_ARM_MOVW_ABS_NC against `a local symbol' can not be used when making a shared object; recompile with -fPIC
+ $BuildCmd .= " -fPIC";
+ $BuildCmd_Test .= " -fPIC";
+ }
+ }
+ elsif($OSgroup eq "macos")
+ { # using GCC -dynamiclib
+ if($Lang eq "C")
+ {
+ $BuildCmd = $GCC_PATH." -dynamiclib -fkeep-inline-functions libsample.$Ext -o libsample.$LIB_EXT";
+ $BuildCmd_Test = $GCC_PATH." test.$Ext libsample.$LIB_EXT -o test";
+ }
+ else
+ { # C++
+ $BuildCmd = $GCC_PATH." -dynamiclib -fkeep-inline-functions -x c++ libsample.$Ext -lstdc++ -o libsample.$LIB_EXT";
+ $BuildCmd_Test = $GCC_PATH." -x c++ test.$Ext libsample.$LIB_EXT -o test";
+ }
+ }
+ else
+ { # default unix-like
+ # symbian target
+ if($Lang eq "C")
+ {
+ $BuildCmd = $GCC_PATH." -shared -fkeep-inline-functions libsample.$Ext -o libsample.$LIB_EXT";
+ $BuildCmd_Test = $GCC_PATH." test.$Ext -Wl,libsample.$LIB_EXT -o test";
+ }
+ else
+ { # C++
+ $BuildCmd = $GCC_PATH." -shared -fkeep-inline-functions -x c++ libsample.$Ext -lstdc++ -o libsample.$LIB_EXT";
+ $BuildCmd_Test = $GCC_PATH." -x c++ test.$Ext -Wl,libsample.$LIB_EXT -o test";
+ }
+ }
+ my $MkContent = "all:\n\t$BuildCmd\ntest:\n\t$BuildCmd_Test\n";
+ if($OSgroup eq "windows") {
+ $MkContent .= "clean:\n\tdel test libsample.so\n";
+ }
+ else {
+ $MkContent .= "clean:\n\trm test libsample.so\n";
+ }
+ writeFile("$Path_v1/Makefile", $MkContent);
+ writeFile("$Path_v2/Makefile", $MkContent);
+ system("cd $Path_v1 && $BuildCmd >build-log.txt 2>&1");
+ if($?) {
+ exitStatus("Error", "can't compile \'$Path_v1/libsample.$Ext\'");
+ }
+ system("cd $Path_v2 && $BuildCmd >build-log.txt 2>&1");
+ if($?) {
+ exitStatus("Error", "can't compile \'$Path_v2/libsample.$Ext\'");
+ }
+ # running the tool
+ my @Cmd = ("perl", $0, "-l", $LibName, "-d1", "$LibName/v1.xml", "-d2", "$LibName/v2.xml");
+ if($TestDump) {
+ @Cmd = (@Cmd, "-use-dumps");
+ }
+ if($GCC_PATH ne "gcc") {
+ @Cmd = (@Cmd, "-cross-gcc", $GCC_PATH);
+ }
+ if($Quiet)
+ { # quiet mode
+ @Cmd = (@Cmd, "-quiet");
+ }
+ if($ExtendedCheck)
+ { # extended mode
+ @Cmd = (@Cmd, "-extended");
+ if($Lang eq "C") {
+ @Cmd = (@Cmd, "-lang", "C");
+ }
+ }
+ if($LogMode eq "n") {
+ @Cmd = (@Cmd, "-logging-mode", "n");
+ }
+ elsif($Quiet) {
+ @Cmd = (@Cmd, "-logging-mode", "a");
+ }
+ if($ReportFormat) {
+ @Cmd = (@Cmd, "-report-format", $ReportFormat);
+ }
+ if($Debug)
+ { # debug mode
+ @Cmd = (@Cmd, "-debug");
+ printMsg("INFO", "@Cmd");
+ }
+ system(@Cmd);
+ my $RPath = "compat_reports/$LibName/1.0_to_2.0/abi_compat_report.$ReportFormat";
+ my $NProblems = 0;
+ if($ReportFormat eq "xml")
+ {
+ my $Content = readFile($RPath);
+ if(my $PSummary = parseTag(\$Content, "problem_summary"))
+ {
+ $NProblems += int(parseTag(\$PSummary, "removed_symbols"));
+ if(my $TProblems = parseTag(\$PSummary, "problems_with_types"))
+ {
+ $NProblems += int(parseTag(\$TProblems, "high"));
+ $NProblems += int(parseTag(\$TProblems, "medium"));
+ }
+ if(my $IProblems = parseTag(\$PSummary, "problems_with_symbols"))
+ {
+ $NProblems += int(parseTag(\$IProblems, "high"));
+ $NProblems += int(parseTag(\$IProblems, "medium"));
+ }
+ }
+ }
+ else
+ {
+ my $MetaData = readAttributes($RPath);
+ $NProblems += $MetaData->{"removed"};
+ $NProblems += $MetaData->{"type_problems_high"}+$MetaData->{"type_problems_medium"};
+ $NProblems += $MetaData->{"interface_problems_high"}+$MetaData->{"interface_problems_medium"};
+ }
+ if(($LibName eq "libsample_c" and $NProblems>30)
+ or ($LibName eq "libsample_cpp" and $NProblems>60)) {
+ printMsg("INFO", "result: SUCCESS ($NProblems problems found)\n");
+ }
+ else {
+ printMsg("ERROR", "result: FAILED ($NProblems problems found)\n");
+ }
+}
+
+return 1; \ No newline at end of file
diff --git a/modules/Internals/Styles/.svn/all-wcprops b/modules/Internals/Styles/.svn/all-wcprops
new file mode 100644
index 0000000..2efa661
--- /dev/null
+++ b/modules/Internals/Styles/.svn/all-wcprops
@@ -0,0 +1,23 @@
+K 25
+svn:wc:ra_dav:version-url
+V 70
+/svn/abi-compliance-checker/!svn/ver/52/trunk/modules/Internals/Styles
+END
+CompatReport.css
+K 25
+svn:wc:ra_dav:version-url
+V 87
+/svn/abi-compliance-checker/!svn/ver/52/trunk/modules/Internals/Styles/CompatReport.css
+END
+SymbolsList.css
+K 25
+svn:wc:ra_dav:version-url
+V 86
+/svn/abi-compliance-checker/!svn/ver/52/trunk/modules/Internals/Styles/SymbolsList.css
+END
+CmpSystems.css
+K 25
+svn:wc:ra_dav:version-url
+V 85
+/svn/abi-compliance-checker/!svn/ver/52/trunk/modules/Internals/Styles/CmpSystems.css
+END
diff --git a/modules/Internals/Styles/.svn/entries b/modules/Internals/Styles/.svn/entries
new file mode 100644
index 0000000..849d9fd
--- /dev/null
+++ b/modules/Internals/Styles/.svn/entries
@@ -0,0 +1,130 @@
+10
+
+dir
+67
+http://forge.ispras.ru/svn/abi-compliance-checker/trunk/modules/Internals/Styles
+http://forge.ispras.ru/svn/abi-compliance-checker
+
+
+
+2011-11-11T14:33:53.617108Z
+52
+aponomarenko
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+a821b6f2-9a20-4ec6-9ceb-7d4f98b805d9
+
+CompatReport.css
+file
+
+
+
+
+2011-11-11T12:09:35.000000Z
+8d59b5188c486d1c9666cf4ab339b749
+2011-11-11T14:33:53.617108Z
+52
+aponomarenko
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4140
+
+SymbolsList.css
+file
+
+
+
+
+2011-11-11T12:01:26.000000Z
+249683c5654907df6e6eb6104af2ed93
+2011-11-11T14:33:53.617108Z
+52
+aponomarenko
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1099
+
+CmpSystems.css
+file
+
+
+
+
+2011-11-11T12:11:14.000000Z
+235ce705773be0ba620a05f92de972dd
+2011-11-11T14:33:53.617108Z
+52
+aponomarenko
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1003
+
diff --git a/modules/Internals/Styles/.svn/text-base/CmpSystems.css.svn-base b/modules/Internals/Styles/.svn/text-base/CmpSystems.css.svn-base
new file mode 100644
index 0000000..f36e865
--- /dev/null
+++ b/modules/Internals/Styles/.svn/text-base/CmpSystems.css.svn-base
@@ -0,0 +1,62 @@
+body {
+ font-family:Arial;
+ font-size:14px;
+ background:#ffffff;
+ color:Black;
+ padding-left:15px;
+}
+hr {
+ color:Black;
+ background-color:Black;
+ height:1px;
+ border:0;
+}
+h1 {
+ margin-bottom:3px;
+ padding-bottom:3px;
+ font-size:26px;
+ white-space:nowrap;
+}
+table.wikitable {
+ border-collapse:collapse;
+ margin:1em 1em 1em 0;
+ background:#f9f9f9;
+ border:1px #aaaaaa solid;
+}
+table.wikitable td, th {
+ border:1px #aaaaaa solid;
+ text-align:center;
+ padding:0.2em;
+ padding-left:5px;
+ padding-right:5px;
+ white-space:nowrap;
+}
+table.wikitable th {
+ background:#f2f2f2;
+}
+table.wikitable td.left {
+ text-align:left;
+ background-color:#f2f2f2;
+}
+td.passed {
+ background-color:#CCFFCC;
+}
+td.warning {
+ background-color:#F4F4AF;
+}
+td.failed {
+ background-color:#FFC3CE;
+}
+td.new {
+ background-color:#C6DEFF;
+}
+a.default {
+ color:#336699;
+}
+th.severity {
+ width:85px;
+ color:Black;
+}
+sup {
+ font-size:10px;
+} \ No newline at end of file
diff --git a/modules/Internals/Styles/.svn/text-base/CompatReport.css.svn-base b/modules/Internals/Styles/.svn/text-base/CompatReport.css.svn-base
new file mode 100644
index 0000000..a2c0d4d
--- /dev/null
+++ b/modules/Internals/Styles/.svn/text-base/CompatReport.css.svn-base
@@ -0,0 +1,236 @@
+body {
+ font-family:Arial;
+ color:Black;
+ font-size:14px;
+}
+hr {
+ color:Black;
+ background-color:Black;
+ height:1px;
+ border:0;
+}
+h1 {
+ margin-bottom:0px;
+ padding-bottom:0px;
+ font-size:26px;
+}
+h2 {
+ margin-bottom:0px;
+ padding-bottom:0px;
+ font-size:20px;
+ white-space:nowrap;
+}
+span.section {
+ font-weight:bold;
+ cursor:pointer;
+ margin-left:7px;
+ font-size:16px;
+ color:#003E69;
+ white-space:nowrap;
+}
+span.new_signature {
+ font-weight:bold;
+ margin-left:28px;
+ font-size:16px;
+ color:#003E69;
+}
+span.new_signature_label {
+ margin-left:28px;
+ font-size:14px;
+ color:Black;
+}
+span:hover.section {
+ color:#336699;
+}
+span.section_affected {
+ cursor:pointer;
+ margin-left:7px;
+ font-size:14px;
+ color:#cc3300;
+}
+span.section_info {
+ cursor:pointer;
+ margin-left:7px;
+ font-size:14px;
+ color:Black;
+}
+span.extendable {
+ font-weight:100;
+ font-size:16px;
+}
+span.h_name {
+ color:#cc3300;
+ font-size:14px;
+ font-weight:bold;
+}
+div.h_list {
+ padding-left:10px;
+ color:#333333;
+ font-size:15px;
+}
+span.ns_title {
+ margin-left:2px;
+ color:#408080;
+ font-size:13px;
+}
+span.ns {
+ color:#408080;
+ font-size:13px;
+ font-weight:bold;
+}
+div.lib_list {
+ padding-left:10px;
+ color:#333333;
+ font-size:15px;
+}
+span.lib_name {
+ color:Green;
+ font-size:14px;
+ font-weight:bold;
+}
+span.iname {
+ font-weight:bold;
+ font-size:16px;
+ color:#003E69;
+ margin-left:7px;
+}
+span.iname_b {
+ font-weight:bold;
+ font-size:15px;
+ color:#333333;
+}
+span.int_p {
+ font-weight:normal;
+ white-space:normal;
+}
+div.affect {
+ padding-left:15px;
+ padding-bottom:4px;
+ font-size:14px;
+ font-style:italic;
+ line-height:13px;
+}
+div.affected {
+ padding-left:30px;
+ padding-top:5px;
+}
+table.problems_table {
+ border-collapse:collapse;
+ border:1px outset black;
+ line-height:16px;
+ margin-left:15px;
+ margin-top:3px;
+ margin-bottom:3px;
+ width:900px;
+}
+table.problems_table td {
+ border:1px solid Gray;
+}
+table.problems_table th {
+ background-color:#eeeeee;
+ color:#333333;
+ font-weight:bold;
+ font-size:13px;
+ font-family:Verdana;
+ border:1px solid Gray;
+ text-align:center;
+ vertical-align:top;
+ white-space:nowrap;
+}
+table.virtual_table {
+ border-collapse:collapse;
+ border:1px outset black;
+ line-height:16px;
+ margin-left:30px;
+ margin-top:3px;
+ width:100px;
+}
+table.virtual_table td {
+ border:1px solid Gray;
+ white-space:nowrap;
+ border:1px solid Gray;
+}
+table.virtual_table th {
+ background-color:#eeeeee;
+ color:#333333;
+ font-weight:bold;
+ font-size:13px;
+ font-family:Verdana;
+ border:1px solid Gray;
+ text-align:center;
+ vertical-align:top;
+ white-space:nowrap;
+}
+td.vtable_red {
+ background-color:#FFCCCC;
+}
+td.vtable_yellow {
+ background-color:#FFFFCC;
+}
+table.summary {
+ border-collapse:collapse;
+ border:1px outset black;
+}
+table.summary th {
+ background-color:#eeeeee;
+ font-weight:100;
+ text-align:left;
+ font-size:15px;
+ white-space:nowrap;
+ border:1px inset gray;
+}
+table.summary td {
+ padding-left:10px;
+ padding-right:5px;
+ text-align:right;
+ font-size:16px;
+ white-space:nowrap;
+ border:1px inset gray;
+}
+table.code_view {
+ cursor:text;
+ margin-top:7px;
+ width:50%;
+ margin-left:20px;
+ font-family:Consolas, Monaco, Monospace;
+ font-size:14px;
+ padding:10px;
+ border:1px solid #e0e8e5;
+ color:#444444;
+ background-color:#eff3f2;
+ overflow:auto;
+}
+table.code_view td {
+ padding-left:15px;
+ text-align:left;
+ white-space:nowrap;
+}
+span.mangled {
+ padding-left:15px;
+ font-size:13px;
+ cursor:text;
+ color:#444444;
+}
+span.symver {
+ color:#333333;
+ font-size:14px;
+ white-space:nowrap;
+}
+span.color_p {
+ font-style:italic;
+ color:Brown;
+}
+span.focus_p {
+ font-style:italic;
+ color:Red;
+}
+span.ttype {
+ font-weight:100;
+}
+span.nowrap {
+ white-space:nowrap;
+}
+span.value {
+ white-space:nowrap;
+ font-weight:bold;
+} \ No newline at end of file
diff --git a/modules/Internals/Styles/.svn/text-base/SymbolsList.css.svn-base b/modules/Internals/Styles/.svn/text-base/SymbolsList.css.svn-base
new file mode 100644
index 0000000..d306f15
--- /dev/null
+++ b/modules/Internals/Styles/.svn/text-base/SymbolsList.css.svn-base
@@ -0,0 +1,73 @@
+body {
+ font-family:Arial;
+ color:Black;
+ font-size:14px;
+}
+hr {
+ color:Black;
+ background-color:Black;
+ height:1px;
+ border:0;
+}
+h1 {
+ font-size:26px;
+}
+span.iname {
+ font-weight:bold;
+ font-size:16px;
+ color:#003E69;
+ margin-left:7px;
+}
+span.section {
+ font-weight:bold;
+ cursor:pointer;
+ margin-left:7px;
+ font-size:16px;
+ color:#003E69;
+ white-space:nowrap;
+}
+span:hover.section {
+ color:#336699;
+}
+span.h_name {
+ color:#cc3300;
+ font-size:14px;
+ font-weight:bold;
+}
+span.ns_title {
+ margin-left:2px;
+ color:#408080;
+ font-size:13px;
+}
+span.ns {
+ color:#408080;
+ font-size:13px;
+ font-weight:bold;
+}
+span.lib_name {
+ color:Green;
+ font-size:14px;
+ font-weight:bold;
+}
+span.int_p {
+ font-weight:normal;
+ white-space:normal;
+}
+span.mangled {
+ padding-left:15px;
+ font-size:13px;
+ cursor:text;
+ color:#444444;
+}
+span.symver {
+ color:#333333;
+ font-size:14px;
+ white-space:nowrap;
+}
+span.color_p {
+ font-style:italic;
+ color:Brown;
+}
+span.nowrap {
+ white-space:nowrap;
+} \ No newline at end of file
diff --git a/modules/Internals/Styles/CmpSystems.css b/modules/Internals/Styles/CmpSystems.css
new file mode 100644
index 0000000..f36e865
--- /dev/null
+++ b/modules/Internals/Styles/CmpSystems.css
@@ -0,0 +1,62 @@
+body {
+ font-family:Arial;
+ font-size:14px;
+ background:#ffffff;
+ color:Black;
+ padding-left:15px;
+}
+hr {
+ color:Black;
+ background-color:Black;
+ height:1px;
+ border:0;
+}
+h1 {
+ margin-bottom:3px;
+ padding-bottom:3px;
+ font-size:26px;
+ white-space:nowrap;
+}
+table.wikitable {
+ border-collapse:collapse;
+ margin:1em 1em 1em 0;
+ background:#f9f9f9;
+ border:1px #aaaaaa solid;
+}
+table.wikitable td, th {
+ border:1px #aaaaaa solid;
+ text-align:center;
+ padding:0.2em;
+ padding-left:5px;
+ padding-right:5px;
+ white-space:nowrap;
+}
+table.wikitable th {
+ background:#f2f2f2;
+}
+table.wikitable td.left {
+ text-align:left;
+ background-color:#f2f2f2;
+}
+td.passed {
+ background-color:#CCFFCC;
+}
+td.warning {
+ background-color:#F4F4AF;
+}
+td.failed {
+ background-color:#FFC3CE;
+}
+td.new {
+ background-color:#C6DEFF;
+}
+a.default {
+ color:#336699;
+}
+th.severity {
+ width:85px;
+ color:Black;
+}
+sup {
+ font-size:10px;
+} \ No newline at end of file
diff --git a/modules/Internals/Styles/CompatReport.css b/modules/Internals/Styles/CompatReport.css
new file mode 100644
index 0000000..a2c0d4d
--- /dev/null
+++ b/modules/Internals/Styles/CompatReport.css
@@ -0,0 +1,236 @@
+body {
+ font-family:Arial;
+ color:Black;
+ font-size:14px;
+}
+hr {
+ color:Black;
+ background-color:Black;
+ height:1px;
+ border:0;
+}
+h1 {
+ margin-bottom:0px;
+ padding-bottom:0px;
+ font-size:26px;
+}
+h2 {
+ margin-bottom:0px;
+ padding-bottom:0px;
+ font-size:20px;
+ white-space:nowrap;
+}
+span.section {
+ font-weight:bold;
+ cursor:pointer;
+ margin-left:7px;
+ font-size:16px;
+ color:#003E69;
+ white-space:nowrap;
+}
+span.new_signature {
+ font-weight:bold;
+ margin-left:28px;
+ font-size:16px;
+ color:#003E69;
+}
+span.new_signature_label {
+ margin-left:28px;
+ font-size:14px;
+ color:Black;
+}
+span:hover.section {
+ color:#336699;
+}
+span.section_affected {
+ cursor:pointer;
+ margin-left:7px;
+ font-size:14px;
+ color:#cc3300;
+}
+span.section_info {
+ cursor:pointer;
+ margin-left:7px;
+ font-size:14px;
+ color:Black;
+}
+span.extendable {
+ font-weight:100;
+ font-size:16px;
+}
+span.h_name {
+ color:#cc3300;
+ font-size:14px;
+ font-weight:bold;
+}
+div.h_list {
+ padding-left:10px;
+ color:#333333;
+ font-size:15px;
+}
+span.ns_title {
+ margin-left:2px;
+ color:#408080;
+ font-size:13px;
+}
+span.ns {
+ color:#408080;
+ font-size:13px;
+ font-weight:bold;
+}
+div.lib_list {
+ padding-left:10px;
+ color:#333333;
+ font-size:15px;
+}
+span.lib_name {
+ color:Green;
+ font-size:14px;
+ font-weight:bold;
+}
+span.iname {
+ font-weight:bold;
+ font-size:16px;
+ color:#003E69;
+ margin-left:7px;
+}
+span.iname_b {
+ font-weight:bold;
+ font-size:15px;
+ color:#333333;
+}
+span.int_p {
+ font-weight:normal;
+ white-space:normal;
+}
+div.affect {
+ padding-left:15px;
+ padding-bottom:4px;
+ font-size:14px;
+ font-style:italic;
+ line-height:13px;
+}
+div.affected {
+ padding-left:30px;
+ padding-top:5px;
+}
+table.problems_table {
+ border-collapse:collapse;
+ border:1px outset black;
+ line-height:16px;
+ margin-left:15px;
+ margin-top:3px;
+ margin-bottom:3px;
+ width:900px;
+}
+table.problems_table td {
+ border:1px solid Gray;
+}
+table.problems_table th {
+ background-color:#eeeeee;
+ color:#333333;
+ font-weight:bold;
+ font-size:13px;
+ font-family:Verdana;
+ border:1px solid Gray;
+ text-align:center;
+ vertical-align:top;
+ white-space:nowrap;
+}
+table.virtual_table {
+ border-collapse:collapse;
+ border:1px outset black;
+ line-height:16px;
+ margin-left:30px;
+ margin-top:3px;
+ width:100px;
+}
+table.virtual_table td {
+ border:1px solid Gray;
+ white-space:nowrap;
+ border:1px solid Gray;
+}
+table.virtual_table th {
+ background-color:#eeeeee;
+ color:#333333;
+ font-weight:bold;
+ font-size:13px;
+ font-family:Verdana;
+ border:1px solid Gray;
+ text-align:center;
+ vertical-align:top;
+ white-space:nowrap;
+}
+td.vtable_red {
+ background-color:#FFCCCC;
+}
+td.vtable_yellow {
+ background-color:#FFFFCC;
+}
+table.summary {
+ border-collapse:collapse;
+ border:1px outset black;
+}
+table.summary th {
+ background-color:#eeeeee;
+ font-weight:100;
+ text-align:left;
+ font-size:15px;
+ white-space:nowrap;
+ border:1px inset gray;
+}
+table.summary td {
+ padding-left:10px;
+ padding-right:5px;
+ text-align:right;
+ font-size:16px;
+ white-space:nowrap;
+ border:1px inset gray;
+}
+table.code_view {
+ cursor:text;
+ margin-top:7px;
+ width:50%;
+ margin-left:20px;
+ font-family:Consolas, Monaco, Monospace;
+ font-size:14px;
+ padding:10px;
+ border:1px solid #e0e8e5;
+ color:#444444;
+ background-color:#eff3f2;
+ overflow:auto;
+}
+table.code_view td {
+ padding-left:15px;
+ text-align:left;
+ white-space:nowrap;
+}
+span.mangled {
+ padding-left:15px;
+ font-size:13px;
+ cursor:text;
+ color:#444444;
+}
+span.symver {
+ color:#333333;
+ font-size:14px;
+ white-space:nowrap;
+}
+span.color_p {
+ font-style:italic;
+ color:Brown;
+}
+span.focus_p {
+ font-style:italic;
+ color:Red;
+}
+span.ttype {
+ font-weight:100;
+}
+span.nowrap {
+ white-space:nowrap;
+}
+span.value {
+ white-space:nowrap;
+ font-weight:bold;
+} \ No newline at end of file
diff --git a/modules/Internals/Styles/SymbolsList.css b/modules/Internals/Styles/SymbolsList.css
new file mode 100644
index 0000000..d306f15
--- /dev/null
+++ b/modules/Internals/Styles/SymbolsList.css
@@ -0,0 +1,73 @@
+body {
+ font-family:Arial;
+ color:Black;
+ font-size:14px;
+}
+hr {
+ color:Black;
+ background-color:Black;
+ height:1px;
+ border:0;
+}
+h1 {
+ font-size:26px;
+}
+span.iname {
+ font-weight:bold;
+ font-size:16px;
+ color:#003E69;
+ margin-left:7px;
+}
+span.section {
+ font-weight:bold;
+ cursor:pointer;
+ margin-left:7px;
+ font-size:16px;
+ color:#003E69;
+ white-space:nowrap;
+}
+span:hover.section {
+ color:#336699;
+}
+span.h_name {
+ color:#cc3300;
+ font-size:14px;
+ font-weight:bold;
+}
+span.ns_title {
+ margin-left:2px;
+ color:#408080;
+ font-size:13px;
+}
+span.ns {
+ color:#408080;
+ font-size:13px;
+ font-weight:bold;
+}
+span.lib_name {
+ color:Green;
+ font-size:14px;
+ font-weight:bold;
+}
+span.int_p {
+ font-weight:normal;
+ white-space:normal;
+}
+span.mangled {
+ padding-left:15px;
+ font-size:13px;
+ cursor:text;
+ color:#444444;
+}
+span.symver {
+ color:#333333;
+ font-size:14px;
+ white-space:nowrap;
+}
+span.color_p {
+ font-style:italic;
+ color:Brown;
+}
+span.nowrap {
+ white-space:nowrap;
+} \ No newline at end of file
diff --git a/modules/Internals/SysCheck.pm b/modules/Internals/SysCheck.pm
new file mode 100644
index 0000000..c4871bc
--- /dev/null
+++ b/modules/Internals/SysCheck.pm
@@ -0,0 +1,1730 @@
+###########################################################################
+# Module for ABI Compliance Checker to compare Operating Systems
+#
+# Copyright (C) 2009-2010 The Linux Foundation.
+# Copyright (C) 2009-2011 Institute for System Programming, RAS.
+# Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+# Copyright (C) 2011 ROSA Laboratory.
+#
+# Written by Andrey Ponomarenko
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License or the GNU Lesser
+# General Public License as published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# and the GNU Lesser General Public License along with this program.
+# If not, see <http://www.gnu.org/licenses/>.
+###########################################################################
+use strict;
+use File::Temp qw(tempdir);
+use Cwd qw(abs_path cwd);
+
+my ($Debug, $Quiet, $LogMode, $CheckHeadersOnly, $SystemRoot, $MODULES_DIR, $GCC_PATH,
+$CrossPrefix, $TargetSysInfo, $TargetLibraryName, $CrossGcc, $UseStaticLibs, $NoStdInc, $OStarget);
+my $OSgroup = get_OSgroup();
+my $TMP_DIR = tempdir(CLEANUP=>1);
+my $ORIG_DIR = cwd();
+my $LIB_EXT = getLIB_EXT($OSgroup);
+
+my %SysDescriptor;
+my %Cache;
+
+sub cmpSystems($$$)
+{ # -cmp-systems option handler
+ # should be used with -d1 and -d2 options
+ my ($SPath1, $SPath2, $Opts) = @_;
+ readOpts($Opts);
+ if(not $SPath1) {
+ exitStatus("Error", "the option -d1 should be specified");
+ }
+ elsif(not -d $SPath1) {
+ exitStatus("Access_Error", "can't access directory \'".$SPath1."\'");
+ }
+ elsif(not -d $SPath1."/abi_dumps") {
+ exitStatus("Access_Error", "can't access directory \'".$SPath1."/abi_dumps\'");
+ }
+ if(not $SPath2) {
+ exitStatus("Error", "the option -d2 should be specified");
+ }
+ elsif(not -d $SPath2) {
+ exitStatus("Access_Error", "can't access directory \'".$SPath2."\'");
+ }
+ elsif(not -d $SPath2."/abi_dumps") {
+ exitStatus("Access_Error", "can't access directory \'".$SPath2."/abi_dumps\'");
+ }
+ # sys_dumps/<System>/<Arch>/...
+ my $SystemName1 = get_filename(get_dirname($SPath1));
+ my $SystemName2 = get_filename(get_dirname($SPath2));
+ # sys_dumps/<System>/<Arch>/...
+ my $ArchName = get_filename($SPath1);
+ if($ArchName ne get_filename($SPath2)) {
+ exitStatus("Error", "can't compare systems of different CPU architecture");
+ }
+ if(my $OStarget_Dump = readFile($SPath1."/target.txt"))
+ { # change target
+ $OStarget = $OStarget_Dump;
+ $LIB_EXT = getLIB_EXT($OStarget);
+ }
+ my $GroupByHeaders = 0;
+ if(my $Mode = readFile($SPath1."/mode.txt"))
+ { # change mode
+ if($Mode eq "headers-only")
+ { # -headers-only mode
+ $CheckHeadersOnly = 1;
+ $GroupByHeaders = 1;
+ }
+ if($Mode eq "group-by-headers") {
+ $GroupByHeaders = 1;
+ }
+ }
+ my $SYS_REPORT_PATH = "sys_compat_reports/".$SystemName1."_to_".$SystemName2."/$ArchName";
+ rmtree($SYS_REPORT_PATH);
+ my (%LibSoname1, %LibSoname2) = ();
+ foreach (split(/\n/, readFile($SPath1."/sonames.txt"))) {
+ if(my ($LFName, $Soname) = split(/;/, $_))
+ {
+ if($OStarget eq "symbian") {
+ $Soname=~s/\{.+\}//;
+ }
+ $LibSoname1{$LFName} = $Soname;
+ }
+ }
+ foreach (split(/\n/, readFile($SPath2."/sonames.txt"))) {
+ if(my ($LFName, $Soname) = split(/;/, $_))
+ {
+ if($OStarget eq "symbian") {
+ $Soname=~s/\{.+\}//;
+ }
+ $LibSoname2{$LFName} = $Soname;
+ }
+ }
+ my (%LibV1, %LibV2) = ();
+ foreach (split(/\n/, readFile($SPath1."/versions.txt"))) {
+ if(my ($LFName, $V) = split(/;/, $_)) {
+ $LibV1{$LFName} = $V;
+ }
+ }
+ foreach (split(/\n/, readFile($SPath2."/versions.txt"))) {
+ if(my ($LFName, $V) = split(/;/, $_)) {
+ $LibV2{$LFName} = $V;
+ }
+ }
+ my @Dumps1 = cmd_find($SPath1."/abi_dumps","f","*.tar.gz",1);
+ if(not @Dumps1)
+ { # zip-based dump
+ @Dumps1 = cmd_find($SPath1."/abi_dumps","f","*.zip",1);
+ }
+ my @Dumps2 = cmd_find($SPath2."/abi_dumps","f","*.tar.gz",1);
+ if(not @Dumps2)
+ { # zip-based dump
+ @Dumps2 = cmd_find($SPath2."/abi_dumps","f","*.zip",1);
+ }
+ my (%LibVers1, %LibVers2) = ();
+ foreach my $DPath (@Dumps1)
+ {
+ if(my $Name = isDump($DPath))
+ {
+ my ($Soname, $V) = ($LibSoname1{$Name}, $LibV1{$Name});
+ if(not $V) {
+ $V = parse_libname($Name, "version", $OStarget);
+ }
+ if($GroupByHeaders) {
+ $Soname = $Name;
+ }
+ $LibVers1{$Soname}{$V} = $DPath;
+ }
+ }
+ foreach my $DPath (@Dumps2)
+ {
+ if(my $Name = isDump($DPath))
+ {
+ my ($Soname, $V) = ($LibSoname2{$Name}, $LibV2{$Name});
+ if(not $V) {
+ $V = parse_libname($Name, "version", $OStarget);
+ }
+ if($GroupByHeaders) {
+ $Soname = $Name;
+ }
+ $LibVers2{$Soname}{$V} = $DPath;
+ }
+ }
+ my (%Added, %Removed) = ();
+ my (%ChangedSoname, %TestResults, %SONAME_Changed);
+ if(not $GroupByHeaders)
+ {
+ my %ChangedSoname_Safe = ();
+ foreach my $LName (sort keys(%LibSoname2))
+ { # libcurl.so.3 -> libcurl.so.4 (search for SONAME by the file name)
+ # OS #1 => OS #2
+ if(defined $LibVers2{$LName})
+ { # already registered
+ next;
+ }
+ my $Soname = $LibSoname2{$LName};
+ if(defined $LibVers2{$Soname}
+ and defined $LibVers1{$LName})
+ {
+ $LibVers2{$LName} = $LibVers2{$Soname};
+ $ChangedSoname_Safe{$Soname}=$LName;
+ }
+ }
+ foreach my $LName (sort keys(%LibSoname1))
+ { # libcurl.so.3 -> libcurl.so.4 (search for SONAME by the file name)
+ # OS #1 <= OS #2
+ if(defined $LibVers1{$LName})
+ { # already registered
+ next;
+ }
+ my $Soname = $LibSoname1{$LName};
+ if(defined $LibVers1{$Soname}
+ and defined $LibVers2{$LName}) {
+ $LibVers1{$LName} = $LibVers1{$Soname};
+ }
+ }
+ my (%AddedShort, %RemovedShort) = ();
+ if(not $GroupByHeaders) {
+ printMsg("INFO", "Checking added/removed libs");
+ }
+ foreach my $LName (sort {lc($a) cmp lc($b)} keys(%LibVers1))
+ { # removed libs
+ if(not is_target_lib($LName)) {
+ next;
+ }
+ if(not defined $LibVers1{$LName}) {
+ next;
+ }
+ my @Versions1 = keys(%{$LibVers1{$LName}});
+ if($#Versions1>=1)
+ { # should be only one version
+ next;
+ }
+ if(not defined $LibVers2{$LName}
+ or not keys(%{$LibVers2{$LName}}))
+ { # removed library
+ if(not $LibSoname2{$LName})
+ {
+ $RemovedShort{parse_libname($LName, "name+ext", $OStarget)}{$LName}=1;
+ $Removed{$LName}{"version"}=$Versions1[0];
+ my $ListPath = "info/$LName/symbols.html";
+ createSymbolsList($LibVers1{$LName}{$Versions1[0]},
+ $SYS_REPORT_PATH."/".$ListPath, $LName, $Versions1[0]."-".$SystemName1, $ArchName);
+ $Removed{$LName}{"list"} = $ListPath;
+ }
+ }
+ }
+ foreach my $LName (sort {lc($a) cmp lc($b)} keys(%LibVers2))
+ { # added libs
+ if(not is_target_lib($LName)) {
+ next;
+ }
+ if(not defined $LibVers2{$LName}) {
+ next;
+ }
+ my @Versions2 = keys(%{$LibVers2{$LName}});
+ if($#Versions2>=1)
+ { # should be only one version
+ next;
+ }
+ if($ChangedSoname_Safe{$LName})
+ { # changed soname but added the symbolic link for old-version library
+ next;
+ }
+ if(not defined $LibVers1{$LName}
+ or not keys(%{$LibVers1{$LName}}))
+ { # added library
+ if(not $LibSoname1{$LName})
+ {
+ $AddedShort{parse_libname($LName, "name+ext", $OStarget)}{$LName}=1;
+ $Added{$LName}{"version"}=$Versions2[0];
+ my $ListPath = "info/$LName/symbols.html";
+ createSymbolsList($LibVers2{$LName}{$Versions2[0]},
+ $SYS_REPORT_PATH."/".$ListPath, $LName, $Versions2[0]."-".$SystemName2, $ArchName);
+ $Added{$LName}{"list"} = $ListPath;
+ }
+ }
+ }
+ foreach my $LSName (keys(%AddedShort))
+ { # changed SONAME
+ my @AddedSonames = keys(%{$AddedShort{$LSName}});
+ next if(length(@AddedSonames)!=1);
+ my @RemovedSonames = keys(%{$RemovedShort{$LSName}});
+ next if(length(@RemovedSonames)!=1);
+ $ChangedSoname{$AddedSonames[0]}=$RemovedSonames[0];
+ $ChangedSoname{$RemovedSonames[0]}=$AddedSonames[0];
+ }
+ }
+ foreach my $LName (sort {lc($a) cmp lc($b)} keys(%LibVers1))
+ {
+ if(not is_target_lib($LName)) {
+ next;
+ }
+ my @Versions1 = keys(%{$LibVers1{$LName}});
+ if(not @Versions1 or $#Versions1>=1)
+ { # should be only one version
+ next;
+ }
+ my $LV1 = $Versions1[0];
+ my $DPath1 = $LibVers1{$LName}{$LV1};
+ my @Versions2 = keys(%{$LibVers2{$LName}});
+ if($#Versions2>=1)
+ { # should be only one version
+ next;
+ }
+ my ($LV2, $LName2, $DPath2) = ();
+ if(@Versions2)
+ {
+ $LV2 = $Versions2[0];
+ $DPath2 = $LibVers2{$LName}{$LV2};
+ }
+ elsif($LName2 = $ChangedSoname{$LName})
+ { # changed SONAME
+ @Versions2 = keys(%{$LibVers2{$LName2}});
+ if(not @Versions2 or $#Versions2>=1) {
+ next;
+ }
+ $LV2 = $Versions2[0];
+ $DPath2 = $LibVers2{$LName2}{$LV2};
+ $LName = parse_libname($LName, "name+ext", $OStarget);
+ $SONAME_Changed{$LName} = 1;
+ }
+ else
+ { # removed
+ next;
+ }
+ my ($FV1, $FV2) = ($LV1."-".$SystemName1, $LV2."-".$SystemName2);
+ my $ACC_compare = "perl $0 -l $LName -d1 \"$DPath1\" -d2 \"$DPath2\"";
+ my $LReportPath = "compat_reports/$LName/abi_compat_report.html";
+ my $LReportPath_Full = $SYS_REPORT_PATH."/".$LReportPath;
+ $ACC_compare .= " -report-path \"$LReportPath_Full\"";
+ if($CheckHeadersOnly) {
+ $ACC_compare .= " -headers-only";
+ }
+ if($GroupByHeaders) {
+ $ACC_compare .= " -component header";
+ }
+ if($Quiet)
+ { # quiet mode
+ $ACC_compare .= " -quiet";
+ }
+ if($LogMode eq "n") {
+ $ACC_compare .= " -logging-mode n";
+ }
+ elsif($Quiet) {
+ $ACC_compare .= " -logging-mode a";
+ }
+ if($Debug)
+ { # debug mode
+ $ACC_compare .= " -debug";
+ printMsg("INFO", "$ACC_compare");
+ }
+ printMsg("INFO_C", "Checking $LName: ");
+ system($ACC_compare." 1>$TMP_DIR/null 2>$TMP_DIR/$LName.stderr");
+ if(-s "$TMP_DIR/$LName.stderr")
+ {
+ my $ErrorLog = readFile("$TMP_DIR/$LName.stderr");
+ chomp($ErrorLog);
+ printMsg("INFO", "Failed ($ErrorLog)");
+ }
+ else
+ {
+ printMsg("INFO", "Ok");
+ $TestResults{$LName} = readAttributes($LReportPath_Full);
+ $TestResults{$LName}{"v1"} = $LV1;
+ $TestResults{$LName}{"v2"} = $LV2;
+ $TestResults{$LName}{"path"} = $LReportPath;
+ }
+ }
+ my $SONAME_Title = "SONAME";
+ if($OStarget eq "windows") {
+ $SONAME_Title = "DLL";
+ }
+ elsif($OStarget eq "symbian") {
+ $SONAME_Title = "DSO";
+ }
+ if($GroupByHeaders)
+ { # show the list of headers
+ $SONAME_Title = "Header File";
+ }
+ my $SYS_REPORT = "<h1>Binary compatibility between <span style='color:Blue;'>$SystemName1</span> and <span style='color:Blue;'>$SystemName2</span> on <span style='color:Blue;'>".showArch($ArchName)."</span></h1>\n";
+ # legend
+ $SYS_REPORT .= "<table>
+ <tr><td class='new' width='80px'>Added</td><td class='passed' width='80px'>Compatible</td></tr>
+ <tr><td class='warning'>Warning</td><td class='failed'>Incompatible</td></tr>
+ </table>";
+ $SYS_REPORT .= "<table class='wikitable'>
+ <tr><th rowspan='2'>$SONAME_Title<sup>".(keys(%TestResults) + keys(%Added) + keys(%Removed) - keys(%SONAME_Changed))."</sup></th>";
+ if(not $GroupByHeaders) {
+ $SYS_REPORT .= "<th colspan='2'>VERSION</th>";
+ }
+ $SYS_REPORT .= "<th rowspan='2'>Compatibility</th>
+ <th rowspan='2'>Added<br/>Symbols</th>
+ <th rowspan='2'>Removed<br/>Symbols</th>
+ <th colspan='3' style='white-space:nowrap;'>API Changes / Compatibility Problems</th></tr>";
+ if(not $GroupByHeaders) {
+ $SYS_REPORT .= "<tr><th>$SystemName1</th><th>$SystemName2</th>";
+ }
+ $SYS_REPORT .= "<th class='severity'>High</th><th class='severity'>Medium</th><th class='severity'>Low</th></tr>\n";
+ my %RegisteredPairs = ();
+ foreach my $LName (sort {lc($a) cmp lc($b)} (keys(%TestResults), keys(%Added), keys(%Removed)))
+ {
+ next if($SONAME_Changed{$LName});
+ my $CompatReport = $TestResults{$LName}{"path"};
+ my $Anchor = $LName;
+ $Anchor=~s/\+/p/g;# anchors to libFLAC++ is libFLACpp
+ $Anchor=~s/\~//g;# libqttracker.so.1~6
+ $SYS_REPORT .= "<tr>\n<td class='left'>$LName<a name=\'$Anchor\'></a></td>\n";
+ if(defined $Removed{$LName}) {
+ $SYS_REPORT .= "<td class='failed'>".$Removed{$LName}{"version"}."</td>\n";
+ }
+ elsif(defined $Added{$LName}) {
+ $SYS_REPORT .= "<td class='new'><a href='".$Added{$LName}{"list"}."'>added</a></td>\n";
+ }
+ elsif(not $GroupByHeaders) {
+ $SYS_REPORT .= "<td>".$TestResults{$LName}{"v1"}."</td>\n";
+ }
+ if(defined $Added{$LName})
+ { # added library
+ $SYS_REPORT .= "<td class='new'>".$Added{$LName}{"version"}."</td>\n";
+ $SYS_REPORT .= "<td class='passed'>100%</td>\n";
+ if($RegisteredPairs{$LName}) {
+ # do nothing
+ }
+ elsif(my $To = $ChangedSoname{$LName})
+ {
+ $RegisteredPairs{$To}=1;
+ $SYS_REPORT .= "<td colspan='5' rowspan='2'>SONAME has <a href='".$TestResults{parse_libname($LName, "name+ext", $OStarget)}{"path"}."'>changed</a></td>\n";
+ }
+ else {
+ foreach (1 .. 5) {
+ $SYS_REPORT .= "<td>n/a</td>\n"; # colspan='5'
+ }
+ }
+ $SYS_REPORT .= "</tr>\n";
+ next;
+ }
+ elsif(defined $Removed{$LName})
+ { # removed library
+ $SYS_REPORT .= "<td class='failed'><a href='".$Removed{$LName}{"list"}."'>removed</a></td>\n";
+ $SYS_REPORT .= "<td class='failed'>0%</td>\n";
+ if($RegisteredPairs{$LName}) {
+ # do nothing
+ }
+ elsif(my $To = $ChangedSoname{$LName})
+ {
+ $RegisteredPairs{$To}=1;
+ $SYS_REPORT .= "<td colspan='5' rowspan='2'>SONAME has <a href='".$TestResults{parse_libname($LName, "name+ext", $OStarget)}{"path"}."'>changed</a></td>\n";
+ }
+ else {
+ foreach (1 .. 5) {
+ $SYS_REPORT .= "<td>n/a</td>\n"; # colspan='5'
+ }
+ }
+ $SYS_REPORT .= "</tr>\n";
+ next;
+ }
+ elsif(not $GroupByHeaders) {
+ $SYS_REPORT .= "<td>".$TestResults{$LName}{"v2"}."</td>\n";
+ }
+ if($TestResults{$LName}{"verdict"} eq "compatible") {
+ $SYS_REPORT .= "<td class='passed'><a href=\'$CompatReport\'>100%</a></td>\n";
+ }
+ else
+ {
+ my $Compatible = 100 - $TestResults{$LName}{"affected"};
+ $SYS_REPORT .= "<td class='failed'><a href=\'$CompatReport\'>$Compatible%</a></td>\n";
+ }
+ my $AddedSym="";
+ if(my $Count = $TestResults{$LName}{"added"}) {
+ $AddedSym="<a href='$CompatReport\#Added'>$Count new</a>";
+ }
+ if($AddedSym) {
+ $SYS_REPORT.="<td class='new'>$AddedSym</td>";
+ }
+ else {
+ $SYS_REPORT.="<td class='passed'>0</td>";
+ }
+ my $RemovedSym="";
+ if(my $Count = $TestResults{$LName}{"removed"}) {
+ $RemovedSym="<a href='$CompatReport\#Removed'>$Count removed</a>";
+ }
+ if($RemovedSym) {
+ $SYS_REPORT.="<td class='failed'>$RemovedSym</td>";
+ }
+ else {
+ $SYS_REPORT.="<td class='passed'>0</td>";
+ }
+ my $High="";
+ if(my $Count = $TestResults{$LName}{"type_problems_high"}+$TestResults{$LName}{"interface_problems_high"}) {
+ $High="<a href='$CompatReport\#High_Risk_Problems'>".problem_title($Count)."</a>";
+ }
+ if($High) {
+ $SYS_REPORT.="<td class='failed'>$High</td>";
+ }
+ else {
+ $SYS_REPORT.="<td class='passed'>0</td>";
+ }
+ my $Medium="";
+ if(my $Count = $TestResults{$LName}{"type_problems_medium"}+$TestResults{$LName}{"interface_problems_medium"}) {
+ $Medium="<a href='$CompatReport\#Medium_Risk_Problems'>".problem_title($Count)."</a>";
+ }
+ if($Medium) {
+ $SYS_REPORT.="<td class='failed'>$Medium</td>";
+ }
+ else {
+ $SYS_REPORT.="<td class='passed'>0</td>";
+ }
+ my $Low="";
+ if(my $Count = $TestResults{$LName}{"type_problems_low"}+$TestResults{$LName}{"interface_problems_low"}+$TestResults{$LName}{"changed_constants"}) {
+ $Low="<a href='$CompatReport\#Low_Risk_Problems'>".warning_title($Count)."</a>";
+ }
+ if($Low) {
+ $SYS_REPORT.="<td class='warning'>$Low</td>";
+ }
+ else {
+ $SYS_REPORT.="<td class='passed'>0</td>";
+ }
+ $SYS_REPORT .= "</tr>\n";
+ }
+ my @META_DATA = ();
+ my %Stat = (
+ "total"=>int(keys(%TestResults)),
+ "added"=>int(keys(%Added)),
+ "removed"=>int(keys(%Removed))
+ );
+ foreach ("added", "removed")
+ {
+ my $Kind = $_."_interfaces";
+ foreach my $LName (keys(%TestResults)) {
+ $Stat{$Kind} += $TestResults{$LName}{$_};
+ }
+ push(@META_DATA, $Kind.":".$Stat{$Kind});
+ }
+ foreach my $T ("type", "interface")
+ {
+ foreach my $S ("high", "medium", "low")
+ {
+ my $Kind = $T."_problems_".$S;
+ foreach my $LName (keys(%TestResults)) {
+ $Stat{$Kind} += $TestResults{$LName}{$Kind};
+ }
+ push(@META_DATA, $Kind.":".$Stat{$Kind});
+ }
+ }
+ foreach my $LName (keys(%TestResults))
+ {
+ foreach ("affected", "changed_constants") {
+ $Stat{$_} += $TestResults{$LName}{$_};
+ }
+ if(not defined $Stat{"verdict"}
+ and $TestResults{$LName}{"verdict"} eq "incompatible") {
+ $Stat{"verdict"} = "incompatible";
+ }
+ }
+ if(not defined $Stat{"verdict"}) {
+ $Stat{"verdict"} = "compatible";
+ }
+ if($Stat{"total"}) {
+ $Stat{"affected"} /= $Stat{"total"};
+ }
+ else {
+ $Stat{"affected"} = 0;
+ }
+ $Stat{"affected"} = show_number($Stat{"affected"});
+ if($Stat{"verdict"}>1) {
+ $Stat{"verdict"} = 1;
+ }
+ push(@META_DATA, "changed_constants:".$Stat{"changed_constants"});
+ push(@META_DATA, "tool_version:".get_dumpversion("perl $0"));
+ foreach ("removed", "added", "total", "affected", "verdict") {
+ @META_DATA = ($_.":".$Stat{$_}, @META_DATA);
+ }
+
+ # bottom header
+ $SYS_REPORT .= "<tr><th rowspan='2'>$SONAME_Title</th>";
+ if(not $GroupByHeaders) {
+ $SYS_REPORT .= "<th>$SystemName1</th><th>$SystemName2</th>";
+ }
+ $SYS_REPORT .= "<th rowspan='2'>Compatibility</th>
+ <th rowspan='2'>Added<br/>Symbols</th>
+ <th rowspan='2'>Removed<br/>Symbols</th>
+ <th class='severity'>High</th><th class='severity'>Medium</th><th class='severity'>Low</th></tr>";
+ if(not $GroupByHeaders) {
+ $SYS_REPORT .= "<tr><th colspan='2'>VERSION</th>";
+ }
+ $SYS_REPORT .= "<th colspan='3' style='white-space:nowrap;'>API Changes / Compatibility Problems</th></tr>\n";
+ $SYS_REPORT .= "</table>";
+ my $Title = "$SystemName1 to $SystemName2 binary compatibility report";
+ my $Keywords = "compatibility, $SystemName1, $SystemName2, API, changes";
+ my $Description = "Binary compatibility between $SystemName1 and $SystemName2 on ".showArch($ArchName);
+ my $Styles = readStyles("CmpSystems.css");
+ writeFile($SYS_REPORT_PATH."/abi_compat_report.html", "<!-\- ".join(";", @META_DATA)." -\->\n".composeHTML_Head($Title, $Keywords, $Description, $Styles)."\n<body>
+ <div>$SYS_REPORT</div>
+ <br/><br/><br/><hr/>
+ ".getReportFooter($SystemName2)."
+ <div style='height:999px;'></div>\n</body></html>");
+ printMsg("INFO", "see detailed report:\n $SYS_REPORT_PATH/abi_compat_report.html");
+}
+
+sub readSystemDescriptor($)
+{
+ my $Content = $_[0];
+ $Content=~s/\/\*(.|\n)+?\*\///g;
+ $Content=~s/<\!--(.|\n)+?-->//g;
+ $SysDescriptor{"Name"} = parseTag(\$Content, "name");
+ my @Tools = ();
+ if(not $SysDescriptor{"Name"}) {
+ exitStatus("Error", "system name is not specified (<name> section)");
+ }
+ foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "libs")))
+ { # target libs
+ if(not -e $Path) {
+ exitStatus("Access_Error", "can't access \'$Path\'");
+ }
+ $Path = get_abs_path($Path);
+ $SysDescriptor{"Libs"}{clean_path($Path)} = 1;
+ }
+ foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs")))
+ { # target libs
+ if(not -d $Path) {
+ exitStatus("Access_Error", "can't access directory \'$Path\'");
+ }
+ $Path = get_abs_path($Path);
+ $SysDescriptor{"SearchLibs"}{clean_path($Path)} = 1;
+ }
+ foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "headers")))
+ {
+ if(not -e $Path) {
+ exitStatus("Access_Error", "can't access \'$Path\'");
+ }
+ $Path = get_abs_path($Path);
+ $SysDescriptor{"Headers"}{clean_path($Path)} = 1;
+ }
+ foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers")))
+ {
+ if(not -d $Path) {
+ exitStatus("Access_Error", "can't access directory \'$Path\'");
+ }
+ $Path = get_abs_path($Path);
+ $SysDescriptor{"SearchHeaders"}{clean_path($Path)} = 1;
+ }
+ foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools")))
+ {
+ if(not -d $Path) {
+ exitStatus("Access_Error", "can't access directory \'$Path\'");
+ }
+ $Path = get_abs_path($Path);
+ $Path = clean_path($Path);
+ $SysDescriptor{"Tools"}{$Path} = 1;
+ push(@Tools, $Path);
+ }
+ foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "gcc_options"))) {
+ $SysDescriptor{"GccOpts"}{clean_path($Path)} = 1;
+ }
+ if($SysDescriptor{"CrossPrefix"} = parseTag(\$Content, "cross_prefix"))
+ { # <cross_prefix> section of XML descriptor
+ $CrossPrefix = $SysDescriptor{"CrossPrefix"};
+ }
+ elsif($CrossPrefix)
+ { # -cross-prefix tool option
+ $SysDescriptor{"CrossPrefix"} = $CrossPrefix;
+ }
+ $SysDescriptor{"Defines"} = parseTag(\$Content, "defines");
+ if($SysDescriptor{"Image"} = parseTag(\$Content, "image"))
+ { # <image>
+ # FIXME: isn't implemented yet
+ if(not -f $SysDescriptor{"Image"}) {
+ exitStatus("Access_Error", "can't access \'".$SysDescriptor{"Image"}."\'");
+ }
+ }
+ return {"Tools"=>\@Tools,"CrossPrefix"=>$CrossPrefix};
+}
+
+sub readOpts($)
+{
+ my $S = $_[0];
+ $OStarget = $S->{"OStarget"};
+ $Debug = $S->{"Debug"};
+ $Quiet = $S->{"Quiet"};
+ $LogMode = $S->{"LogMode"};
+ $CheckHeadersOnly = $S->{"CheckHeadersOnly"};
+
+ $SystemRoot = $S->{"SystemRoot"};
+ $MODULES_DIR = $S->{"MODULES_DIR"};
+ $GCC_PATH = $S->{"GCC_PATH"};
+ $TargetSysInfo = $S->{"TargetSysInfo"};
+ $CrossPrefix = $S->{"CrossPrefix"};
+ $TargetLibraryName = $S->{"TargetLibraryName"};
+ $CrossGcc = $S->{"CrossGcc"};
+ $UseStaticLibs = $S->{"UseStaticLibs"};
+ $NoStdInc = $S->{"NoStdInc"};
+}
+
+sub check_list($$)
+{
+ my ($Item, $Skip) = @_;
+ return 0 if(not $Skip);
+ my @Patterns = @{$Skip};
+ foreach my $Pattern (@Patterns)
+ {
+ if($Pattern=~s/\*/.*/g)
+ { # wildcards
+ if($Item=~/$Pattern/) {
+ return 1;
+ }
+ }
+ elsif($Pattern=~/[\/\\]/)
+ { # directory
+ if($Item=~/\Q$Pattern\E/) {
+ return 1;
+ }
+ }
+ elsif($Item eq $Pattern
+ or get_filename($Item) eq $Pattern)
+ { # by name
+ return 1;
+ }
+ }
+ return 0;
+}
+
+sub filter_format($)
+{
+ my $FiltRef = $_[0];
+ foreach my $Entry (keys(%{$FiltRef}))
+ {
+ foreach my $Filt (@{$FiltRef->{$Entry}})
+ {
+ if($Filt=~/[\/\\]/) {
+ $Filt = path_format($Filt, $OSgroup);
+ }
+ }
+ }
+}
+
+sub read_sys_descriptor($)
+{
+ my $Path = $_[0];
+ my $Content = readFile($Path);
+ my %Tags = (
+ "headers" => "mf",
+ "skip_headers" => "mf",
+ "skip_libs" => "mf",
+ "include_preamble" => "mf",
+ "non_self_compiled" => "mf",
+ "add_include_paths" => "mf",
+ "gcc_options" => "m",
+ "skip_symbols" => "m",
+ "skip_types" => "m",
+ "ignore_symbols" => "h",
+ "defines" => "s"
+ );
+ my %DInfo = ();
+ foreach my $Tag (keys(%Tags))
+ {
+ if(my $TContent = parseTag(\$Content, $Tag))
+ {
+ if($Tags{$Tag}=~/m/)
+ { # multi-line (+order)
+ my @Items = split(/\s*\n\s*/, $TContent);
+ $DInfo{$Tag} = [];
+ foreach my $Item (@Items)
+ {
+ if($Tags{$Tag}=~/f/) {
+ $Item = path_format($Item, $OSgroup);
+ }
+ push(@{$DInfo{$Tag}}, $Item);
+ }
+
+ }
+ elsif($Tags{$Tag}=~/s/)
+ { # single element
+ $DInfo{$Tag} = $TContent;
+ }
+ else
+ { # hash array
+ my @Items = split(/\s*\n\s*/, $TContent);
+ foreach my $Item (@Items) {
+ $DInfo{$Tag}{$Item}=1;
+ }
+ }
+ }
+ }
+ return \%DInfo;
+}
+
+sub read_sys_info($)
+{
+ my $Target = $_[0];
+ my $SYS_INFO_PATH = $MODULES_DIR."/Targets";
+ if(-d $SYS_INFO_PATH."/".$Target)
+ { # symbian, windows
+ $SYS_INFO_PATH .= "/".$Target;
+ }
+ else
+ { # default
+ $SYS_INFO_PATH .= "/unix";
+ }
+ if($TargetSysInfo)
+ { # user-defined target
+ $SYS_INFO_PATH = $TargetSysInfo;
+ }
+ if(not -d $SYS_INFO_PATH) {
+ exitStatus("Module_Error", "can't access \'$SYS_INFO_PATH\'");
+ }
+ # Library Specific Info
+ my %SysInfo = ();
+ if(not -d $SYS_INFO_PATH."/descriptors/") {
+ exitStatus("Module_Error", "can't access \'$SYS_INFO_PATH/descriptors\'");
+ }
+ foreach my $DPath (cmd_find($SYS_INFO_PATH."/descriptors/","f","",1))
+ {
+ my $LSName = get_filename($DPath);
+ $LSName=~s/\.xml\Z//;
+ $SysInfo{$LSName} = read_sys_descriptor($DPath);
+ }
+ # Exceptions
+ if(check_gcc_version($GCC_PATH, "4.4"))
+ { # exception for libstdc++
+ $SysInfo{"libstdc++"}{"gcc_options"} = ["-std=c++0x"];
+ }
+ if($OStarget eq "symbian")
+ { # exception for libstdcpp
+ $SysInfo{"libstdcpp"}{"defines"} = "namespace std { struct nothrow_t {}; }";
+ }
+ if($SysDescriptor{"Name"}=~/maemo/i)
+ { # GL/gl.h: No such file
+ $SysInfo{"libSDL"}{"skip_headers"}=["SDL_opengl.h"];
+ }
+ if($OStarget eq "linux") {
+ $SysInfo{"libboost_"}{"headers"} = ["/boost/", "/asio/"];
+ }
+ # Common Info
+ if(not -f $SYS_INFO_PATH."/common.xml") {
+ exitStatus("Module_Error", "can't access \'$SYS_INFO_PATH/common.xml\'");
+ }
+ my $SysCInfo = read_sys_descriptor($SYS_INFO_PATH."/common.xml");
+ my @CompilerOpts = ();
+ if($SysDescriptor{"Name"}=~/maemo|meego/i) {
+ push(@CompilerOpts, "-DMAEMO_CHANGES", "-DM_APPLICATION_NAME=\\\"app\\\"");
+ }
+ if(my @Opts = keys(%{$SysDescriptor{"GccOpts"}})) {
+ push(@CompilerOpts, @Opts);
+ }
+ if(@CompilerOpts)
+ {
+ if(not $SysCInfo->{"gcc_options"}) {
+ $SysCInfo->{"gcc_options"} = [];
+ }
+ push(@{$SysCInfo->{"gcc_options"}}, @CompilerOpts);
+ }
+ foreach my $Name (keys(%SysInfo))
+ { # strict headers that should be
+ # matched for only one library
+ if($SysInfo{$Name}{"headers"}) {
+ $SysCInfo->{"sheaders"}{$Name} = $SysInfo{$Name}{"headers"};
+ }
+ }
+ return (\%SysInfo, $SysCInfo);
+}
+
+sub get_binversion($)
+{
+ my $Path = $_[0];
+ if($OStarget eq "windows"
+ and $LIB_EXT eq "dll")
+ { # get version of DLL using "sigcheck"
+ my $SigcheckCmd = get_CmdPath("sigcheck");
+ if(not $SigcheckCmd) {
+ return "";
+ }
+ my $VInfo = `$SigcheckCmd -n $Path 2>$TMP_DIR/null`;
+ $VInfo=~s/\s*\(.*\)\s*//;
+ chomp($VInfo);
+ return $VInfo;
+ }
+ return "";
+}
+
+sub get_soname($)
+{
+ my $Path = $_[0];
+ return if(not $Path or not -e $Path);
+ if(defined $Cache{"get_soname"}{$Path}) {
+ return $Cache{"get_soname"}{$Path};
+ }
+ my $ObjdumpCmd = get_CmdPath("objdump");
+ if(not $ObjdumpCmd) {
+ exitStatus("Not_Found", "can't find \"objdump\"");
+ }
+ my $SonameCmd = "$ObjdumpCmd -x $Path 2>$TMP_DIR/null";
+ if($OSgroup eq "windows") {
+ $SonameCmd .= " | find \"SONAME\"";
+ }
+ else {
+ $SonameCmd .= " | grep SONAME";
+ }
+ if(my $SonameInfo = `$SonameCmd`) {
+ if($SonameInfo=~/SONAME\s+([^\s]+)/) {
+ return ($Cache{"get_soname"}{$Path} = $1);
+ }
+ }
+ return ($Cache{"get_soname"}{$Path}="");
+}
+
+sub dumpSystem($)
+{ # -dump-system option handler
+ # should be used with -sysroot and -cross-gcc options
+ my $Opts = $_[0];
+ readOpts($Opts);
+ my $SYS_DUMP_PATH = "sys_dumps/".$SysDescriptor{"Name"}."/".getArch(1);
+ if(not $TargetLibraryName) {
+ rmtree($SYS_DUMP_PATH);
+ }
+ my (@SystemLibs, @SysHeaders) = ();
+ foreach my $Path (keys(%{$SysDescriptor{"Libs"}}))
+ {
+ if(not -e $Path) {
+ exitStatus("Access_Error", "can't access \'$Path\'");
+ }
+ if(-d $Path)
+ {
+ if(my @SubLibs = find_libs($Path,"",1)) {
+ push(@SystemLibs, @SubLibs);
+ }
+ $SysDescriptor{"SearchLibs"}{$Path}=1;
+ }
+ else
+ { # single file
+ push(@SystemLibs, $Path);
+ $SysDescriptor{"SearchLibs"}{get_dirname($Path)}=1;
+ }
+ }
+ foreach my $Path (keys(%{$SysDescriptor{"Headers"}}))
+ {
+ if(not -e $Path) {
+ exitStatus("Access_Error", "can't access \'$Path\'");
+ }
+ if(-d $Path)
+ {
+ if(my @SubHeaders = cmd_find($Path,"f","","")) {
+ push(@SysHeaders, @SubHeaders);
+ }
+ $SysDescriptor{"SearchHeaders"}{$Path}=1;
+ }
+ else
+ { # single file
+ push(@SysHeaders, $Path);
+ $SysDescriptor{"SearchHeaders"}{get_dirname($Path)}=1;
+ }
+ }
+ my $GroupByHeaders = 0;
+ if($CheckHeadersOnly)
+ { # -headers-only
+ $GroupByHeaders = 1;
+ # @SysHeaders = optimize_set(@SysHeaders);
+ }
+ elsif($SysDescriptor{"Image"})
+ { # one big image
+ $GroupByHeaders = 1;
+ @SystemLibs = ($SysDescriptor{"Image"});
+ }
+ writeFile($SYS_DUMP_PATH."/target.txt", $OStarget);
+ my (%SysLib_Symbols, %SymbolGroup, %Symbol_SysHeaders,
+ %SysHeader_Symbols, %SysLib_SysHeaders, %MatchByName) = ();
+ my (%Skipped, %Failed, %Success) = ();
+ my (%SysHeaderDir_SysLibs, %SysHeaderDir_SysHeaders) = ();
+ my (%LibPrefixes, %SymbolCounter, %TotalLibs) = ();
+ my %Glibc = map {$_=>1} (
+ "libc",
+ "libpthread"
+ );
+ my ($SysInfo, $SysCInfo) = read_sys_info($OStarget);
+ if(not $GroupByHeaders) {
+ printMsg("INFO", "Indexing sonames ...");
+ }
+ my (%LibSoname, %SysLibVersion) = ();
+ my %DevelPaths = map {$_=>1} @SystemLibs;
+ foreach my $Path (sort keys(%{$SysDescriptor{"SearchLibs"}})) {
+ foreach my $LPath (find_libs($Path,"",1)) {
+ $DevelPaths{$LPath}=1;
+ }
+ }
+ foreach my $LPath (keys(%DevelPaths))
+ { # register SONAMEs
+ my $LName = get_filename($LPath);
+ my $LRelPath = cut_path_prefix($LPath, $SystemRoot);
+ if(not is_target_lib($LName)) {
+ next;
+ }
+ if($OSgroup=~/\A(linux|macos|freebsd)\Z/
+ and $LName!~/\Alib/) {
+ next;
+ }
+ if(my $Soname = get_soname($LPath))
+ {
+ if($OStarget eq "symbian")
+ {
+ if($Soname=~/[\/\\]/)
+ { # L://epoc32/release/armv5/lib/gfxtrans{000a0000}.dso
+ $Soname = get_filename($Soname);
+ }
+ $Soname = lc($Soname);
+ }
+ if(not defined $LibSoname{$LName}) {
+ $LibSoname{$LName}=$Soname;
+ }
+ if(-l $LPath and my $Path = resolve_symlink($LPath))
+ {
+ my $Name = get_filename($Path);
+ if(not defined $LibSoname{$Name}) {
+ $LibSoname{$Name}=$Soname;
+ }
+ }
+ }
+ else
+ { # windows and others
+ $LibSoname{$LName}=$LName;
+ }
+ }
+ my $SONAMES = "";
+ foreach (sort {lc($a) cmp lc($b)} keys(%LibSoname)) {
+ $SONAMES .= $_.";".$LibSoname{$_}."\n";
+ }
+ if(not $GroupByHeaders) {
+ writeFile($SYS_DUMP_PATH."/sonames.txt", $SONAMES);
+ }
+ foreach my $LPath (sort keys(%DevelPaths))
+ {# register VERSIONs
+ my $LName = get_filename($LPath);
+ if(not is_target_lib($LName)
+ and not is_target_lib($LibSoname{$LName})) {
+ next;
+ }
+ if(my $V = get_binversion($LPath))
+ { # binary version
+ $SysLibVersion{$LName} = $V;
+ }
+ elsif(my $V = parse_libname($LName, "version", $OStarget))
+ { # source version
+ $SysLibVersion{$LName} = $V;
+ }
+ elsif($LName=~/([\d\.\-\_]+)\.$LIB_EXT\Z/)
+ { # libfreebl3.so
+ if($1 ne 32 and $1 ne 64) {
+ $SysLibVersion{$LName} = $1;
+ }
+ }
+ }
+ my $VERSIONS = "";
+ foreach (sort {lc($a) cmp lc($b)} keys(%SysLibVersion)) {
+ $VERSIONS .= $_.";".$SysLibVersion{$_}."\n";
+ }
+ if(not $GroupByHeaders) {
+ writeFile($SYS_DUMP_PATH."/versions.txt", $VERSIONS);
+ }
+ my %SysLibs = ();
+ foreach my $LPath (sort @SystemLibs)
+ {
+ my $LName = get_filename($LPath);
+ my $LSName = parse_libname($LName, "short", $OStarget);
+ my $LRelPath = cut_path_prefix($LPath, $SystemRoot);
+ if(not is_target_lib($LName)) {
+ next;
+ }
+ if($OSgroup=~/\A(linux|macos|freebsd)\Z/
+ and $LName!~/\Alib/) {
+ next;
+ }
+ if($OStarget eq "symbian")
+ {
+ if(my $V = parse_libname($LName, "version", $OStarget))
+ { # skip qtcore.dso
+ # register qtcore{00040604}.dso
+ delete($SysLibs{get_dirname($LPath)."\\".$LSName.".".$LIB_EXT});
+ my $MV = parse_libname($LibSoname{$LSName.".".$LIB_EXT}, "version", $OStarget);
+ if($MV and $V ne $MV)
+ { # skip other versions:
+ # qtcore{00040700}.dso
+ # qtcore{00040702}.dso
+ next;
+ }
+ }
+ }
+ if(my $Skip = $SysCInfo->{"skip_libs"})
+ { # do NOT check some libs
+ if(check_list($LRelPath, $Skip)) {
+ next;
+ }
+ }
+ if(-l $LPath)
+ { # symlinks
+ if(my $Path = resolve_symlink($LPath)) {
+ $SysLibs{$Path} = 1;
+ }
+ }
+ elsif(-f $LPath)
+ {
+ if($Glibc{$LSName}
+ and cmd_file($LPath)=~/ASCII/)
+ {# GNU ld scripts (libc.so, libpthread.so)
+ my @Candidates = cmd_find($SystemRoot."/lib","",$LSName.".".$LIB_EXT."*","1");
+ if(@Candidates)
+ {
+ my $Candidate = $Candidates[0];
+ if(-l $Candidate
+ and my $Path = resolve_symlink($Candidate)) {
+ $Candidate = $Path;
+ }
+ $SysLibs{$Candidate} = 1;
+ }
+ }
+ else {
+ $SysLibs{$LPath} = 1;
+ }
+ }
+ }
+ @SystemLibs = ();# clear memory
+ if(not $CheckHeadersOnly)
+ {
+ if($SysDescriptor{"Image"}) {
+ printMsg("INFO", "Reading symbols from image ...");
+ }
+ else {
+ printMsg("INFO", "Reading symbols from libraries ...");
+ }
+ }
+ foreach my $LPath (sort keys(%SysLibs))
+ {
+ my $LRelPath = cut_path_prefix($LPath, $SystemRoot);
+ my $LName = get_filename($LPath);
+ my $Library_Symbol = getSymbols_Lib(1, $LPath, 0, (), "-Weak");
+ my @AllSymbols = keys(%{$Library_Symbol->{$LName}});
+ my $tr_name = translateSymbols(@AllSymbols, 1);
+ foreach my $Symbol (@AllSymbols)
+ {
+ $Symbol=~s/[\@\$]+(.*)\Z//g;
+ if($Symbol=~/\A(_Z|\?)/)
+ {
+ if(skipGlobalData($Symbol)) {
+ next;
+ }
+ if($Symbol=~/(C1|C2|D0|D1|D2)E/)
+ { # do NOT analyze constructors
+ # and destructors
+ next;
+ }
+ my $Unmangled = $tr_name->{$Symbol};
+ $Unmangled=~s/<.+>//g;
+ if($Unmangled=~/\A([\w:]+)/)
+ { # cut out the parameters
+ my @Elems = split(/::/, $1);
+ my ($Class, $Short) = ();
+ $Short = $Elems[$#Elems];
+ if($#Elems>=1) {
+ $Class = $Elems[$#Elems-1];
+ pop(@Elems);
+ }
+ # the short and class name should be
+ # matched in one header file
+ $SymbolGroup{$LRelPath}{$Class} = $Short;
+ foreach my $Sym (@Elems)
+ {
+ if($SysCInfo->{"ignore_symbols"}{$Symbol})
+ { # do NOT match this symbol
+ next;
+ }
+ $SysLib_Symbols{$LPath}{$Sym}=1;
+ if(my $Prefix = getPrefix($Sym)) {
+ $LibPrefixes{$Prefix}{$LName}+=1;
+ }
+ $SymbolCounter{$Sym}{$LName}=1;
+ }
+ }
+ }
+ else
+ {
+ if($SysCInfo->{"ignore_symbols"}{$Symbol})
+ { # do NOT match this symbol
+ next;
+ }
+ $SysLib_Symbols{$LPath}{$Symbol}=1;
+ if(my $Prefix = getPrefix($Symbol)) {
+ $LibPrefixes{$Prefix}{$LName}+=1;
+ }
+ $SymbolCounter{$Symbol}{$LName}=1;
+ }
+ }
+ }
+ if(not $CheckHeadersOnly) {
+ writeFile($SYS_DUMP_PATH."/symbols.txt", Dumper(\%SysLib_Symbols));
+ }
+ my (%DupLibs, %VersionedLibs) = ();
+ foreach my $LPath1 (sort keys(%SysLib_Symbols))
+ { # match duplicated libs
+ # libmenu contains all symbols from libmenuw
+ my $SName = parse_libname(get_filename($LPath1), "shortest", $OStarget);
+ foreach my $LPath2 (sort keys(%SysLib_Symbols))
+ {
+ next if($LPath1 eq $LPath2);
+ if($SName eq parse_libname(get_filename($LPath2), "shortest", $OStarget))
+ { # libpython-X.Y
+ $VersionedLibs{$LPath1}{$LPath2}=1;
+ next;
+ }
+ my $Duplicate=1;
+ foreach (keys(%{$SysLib_Symbols{$LPath1}}))
+ {
+ if(not defined $SysLib_Symbols{$LPath2}{$_}) {
+ $Duplicate=0;
+ last;
+ }
+ }
+ if($Duplicate) {
+ $DupLibs{$LPath1}{$LPath2}=1;
+ }
+ }
+ }
+ foreach my $Prefix (keys(%LibPrefixes))
+ {
+ my @Libs = keys(%{$LibPrefixes{$Prefix}});
+ @Libs = sort {$LibPrefixes{$Prefix}{$b}<=>$LibPrefixes{$Prefix}{$a}} @Libs;
+ $LibPrefixes{$Prefix}=$Libs[0];
+ }
+ printMsg("INFO", "Reading symbols from headers ...");
+ foreach my $HPath (@SysHeaders)
+ {
+ $HPath = path_format($HPath, $OSgroup);
+ my $HRelPath = cut_path_prefix($HPath, $SystemRoot);
+ my ($HDir, $HName) = separate_path($HRelPath);
+ if(is_not_header($HName))
+ { # have a wrong extension: .gch, .in
+ next;
+ }
+ if($HName=~/~\Z/)
+ { # reserved copy
+ next;
+ }
+ if($HRelPath=~/[\/\\]_gen/)
+ { # telepathy-1.0/telepathy-glib/_gen
+ # telepathy-1.0/libtelepathy/_gen-tp-constants-deprecated.h
+ next;
+ }
+ if($HRelPath=~/include[\/\\]linux[\/\\]/)
+ { # kernel-space headers
+ next;
+ }
+ if($HRelPath=~/include[\/\\]asm[\/\\]/)
+ { # asm headers
+ next;
+ }
+ if($HRelPath=~/[\/\\]microb-engine[\/\\]/)
+ { # MicroB engine (Maemo 4)
+ next;
+ }
+ if($HRelPath=~/\Wprivate(\W|\Z)/)
+ { # private directories (include/tcl-private, ...)
+ next;
+ }
+ my $Content = readFile($HPath);
+ $Content=~s/\/\*(.|\n)+?\*\///g;
+ $Content=~s/\/\/.*?\n//g;# remove comments
+ $Content=~s/#\s*define[^\n\\]*(\\\n[^\n\\]*)+\n*//g;# remove defines
+ $Content=~s/#[^\n]*?\n//g;# remove directives
+ $Content=~s/(\A|\n)class\s+\w+;\n//g;# remove forward declarations
+ # FIXME: try to add preprocessing stage
+ foreach my $Symbol (split(/\W+/, $Content))
+ {
+ $Symbol_SysHeaders{$Symbol}{$HRelPath} = 1;
+ $SysHeader_Symbols{$HRelPath}{$Symbol} = 1;
+ }
+ $SysHeaderDir_SysHeaders{$HDir}{$HName} = 1;
+ my $HShort = $HName;
+ $HShort=~s/\.\w+\Z//g;
+ if($HShort=~/\Alib/) {
+ $MatchByName{$HShort} = $HRelPath;
+ }
+ elsif(get_filename(get_dirname($HRelPath))=~/\Alib(.+)\Z/)
+ { # libical/ical.h
+ if($HShort=~/\Q$1\E/) {
+ $MatchByName{"lib".$HShort} = $HRelPath;
+ }
+ }
+ elsif($OStarget eq "windows"
+ and $HShort=~/api\Z/) {
+ $MatchByName{$HShort} = $HRelPath;
+ }
+ }
+ my %SkipDHeaders = (
+ # header files, that should be in the <skip_headers> section
+ # but should be matched in the algorithm
+ # MeeGo 1.2 Harmattan
+ "libtelepathy-qt4" => ["TelepathyQt4/_gen", "client.h",
+ "TelepathyQt4/*-*", "debug.h", "global.h",
+ "properties.h", "Channel", "channel.h", "message.h"],
+ );
+ filter_format(\%SkipDHeaders);
+ if(not $GroupByHeaders) {
+ printMsg("INFO", "Matching symbols ...");
+ }
+ foreach my $LPath (sort keys(%SysLibs))
+ { # matching
+ my $LName = get_filename($LPath);
+ my $LNameSE = parse_libname($LName, "name+ext", $OStarget);
+ my $LRelPath = cut_path_prefix($LPath, $SystemRoot);
+ my $LSName = parse_libname($LName, "short", $OStarget);
+ my $SName = parse_libname($LName, "shortest", $OStarget);
+ if($LRelPath=~/\/debug\//)
+ { # debug libs
+ $Skipped{$LRelPath}=1;
+ next;
+ }
+ $TotalLibs{$LRelPath}=1;
+ $SysLib_SysHeaders{$LRelPath} = ();
+ if(keys(%{$SysLib_Symbols{$LPath}}))
+ { # try to match by name of the header
+ if(my $Path = $MatchByName{$LSName}) {
+ $SysLib_SysHeaders{$LRelPath}{$Path}="exact match ($LSName)";
+ }
+ if(length($SName)>=3
+ and my $Path = $MatchByName{"lib".$SName}) {
+ $SysLib_SysHeaders{$LRelPath}{$Path}="exact match (lib$SName)";
+ }
+ }
+ my (%SymbolDirs, %SymbolFiles) = ();
+ foreach my $Symbol (sort {length($b) cmp length($a)}
+ sort keys(%{$SysLib_Symbols{$LPath}}))
+ {
+ if($SysCInfo->{"ignore_symbols"}{$Symbol}) {
+ next;
+ }
+ if(not $DupLibs{$LPath}
+ and not $VersionedLibs{$LPath}
+ and keys(%{$SymbolCounter{$Symbol}})>=2
+ and my $Prefix = getPrefix($Symbol))
+ { # duplicated symbols
+ if($LibPrefixes{$Prefix}
+ and $LibPrefixes{$Prefix} ne $LName
+ and not $Glibc{$LSName}) {
+ next;
+ }
+ }
+ if(length($Symbol)<=2) {
+ next;
+ }
+ if($Symbol!~/[A-Z_0-9]/
+ and length($Symbol)<10
+ and keys(%{$Symbol_SysHeaders{$Symbol}})>=3)
+ { # undistinguished symbols
+ # FIXME: improve this filter
+ # signalfd (libc.so)
+ # regcomp (libpcreposix.so)
+ next;
+ }
+ if($Symbol=~/\A(_M_|_Rb_|_S_)/)
+ { # _M_insert, _Rb_tree, _S_destroy_c_locale
+ next;
+ }
+ if($Symbol=~/\A[A-Z][a-z]+\Z/)
+ { # Clone, Initialize, Skip, Unlock, Terminate, Chunk
+ next;
+ }
+ if($Symbol=~/\A[A-Z][A-Z]\Z/)
+ { # BC, PC, UP, SP
+ next;
+ }
+ if($Symbol=~/_t\Z/)
+ { # pthread_mutex_t, wchar_t
+ next;
+ }
+ my @SymHeaders = keys(%{$Symbol_SysHeaders{$Symbol}});
+ @SymHeaders = sort {lc($a) cmp lc($b)} @SymHeaders;# sort by name
+ @SymHeaders = sort {length(get_dirname($a))<=>length(get_dirname($b))} @SymHeaders;# sort by length
+ if(length($SName)>=3)
+ { # sort candidate headers by name
+ @SymHeaders = sort {$b=~/\Q$SName\E/i<=>$a=~/\Q$SName\E/i} @SymHeaders;
+ }
+ else
+ { # libz, libX11
+ @SymHeaders = sort {$b=~/lib\Q$SName\E/i<=>$a=~/lib\Q$SName\E/i} @SymHeaders;
+ @SymHeaders = sort {$b=~/\Q$SName\Elib/i<=>$a=~/\Q$SName\Elib/i} @SymHeaders;
+ }
+ @SymHeaders = sort {$b=~/\Q$LSName\E/i<=>$a=~/\Q$LSName\E/i} @SymHeaders;
+ @SymHeaders = sort {$SymbolDirs{get_dirname($b)}<=>$SymbolDirs{get_dirname($a)}} @SymHeaders;
+ @SymHeaders = sort {$SymbolFiles{get_filename($b)}<=>$SymbolFiles{get_filename($a)}} @SymHeaders;
+ foreach my $HRelPath (@SymHeaders)
+ {
+ if(my $Group = $SymbolGroup{$LRelPath}{$Symbol}) {
+ if(not $SysHeader_Symbols{$HRelPath}{$Group}) {
+ next;
+ }
+ }
+ if(my $Search = $SysInfo->{$LSName}{"headers"})
+ { # search for specified headers
+ if(not check_list($HRelPath, $Search)) {
+ next;
+ }
+ }
+ if(my $Skip = $SysInfo->{$LSName}{"skip_headers"})
+ { # do NOT search for some headers
+ if(check_list($HRelPath, $Skip)) {
+ next;
+ }
+ }
+ if(my $Skip = $SysCInfo->{"skip_headers"})
+ { # do NOT search for some headers
+ if(check_list($HRelPath, $Skip)) {
+ next;
+ }
+ }
+ if(my $Skip = $SysInfo->{$LSName}{"non_self_compiled"})
+ { # do NOT search for some headers
+ if(check_list($HRelPath, $Skip)) {
+ $SymbolDirs{get_dirname($HRelPath)}+=1;
+ $SymbolFiles{get_filename($HRelPath)}+=1;
+ next;
+ }
+ }
+ my $Continue = 1;
+ foreach my $Name (keys(%{$SysCInfo->{"sheaders"}}))
+ {
+ if($LSName!~/\Q$Name\E/
+ and check_list($HRelPath, $SysCInfo->{"sheaders"}{$Name}))
+ { # restriction to search for C++ or Boost headers
+ # in the boost/ and c++/ directories only
+ $Continue=0;
+ last;
+ }
+ }
+ if(not $Continue) {
+ next;
+ }
+ $SysLib_SysHeaders{$LRelPath}{$HRelPath}=$Symbol;
+ $SysHeaderDir_SysLibs{get_dirname($HRelPath)}{$LNameSE}=1;
+ $SysHeaderDir_SysLibs{get_dirname(get_dirname($HRelPath))}{$LNameSE}=1;
+ $SymbolDirs{get_dirname($HRelPath)}+=1;
+ $SymbolFiles{get_filename($HRelPath)}+=1;
+ last;# select one header for one symbol
+ }
+ }
+ if(keys(%{$SysLib_SysHeaders{$LRelPath}})) {
+ $Success{$LRelPath}=1;
+ }
+ else {
+ $Failed{$LRelPath}=1;
+ }
+ }
+ if(not $GroupByHeaders)
+ { # matching results
+ writeFile($SYS_DUMP_PATH."/match.txt", Dumper(\%SysLib_SysHeaders));
+ writeFile($SYS_DUMP_PATH."/skipped.txt", join("\n", sort keys(%Skipped)));
+ writeFile($SYS_DUMP_PATH."/failed.txt", join("\n", sort keys(%Failed)));
+ }
+ (%SysLib_Symbols, %SymbolGroup, %Symbol_SysHeaders, %SysHeader_Symbols) = ();# free memory
+ if($GroupByHeaders)
+ {
+ if($SysDescriptor{"Image"} and not $CheckHeadersOnly) {
+ @SysHeaders = keys(%{$SysLib_SysHeaders{$SysDescriptor{"Image"}}});
+ }
+ %SysLib_SysHeaders = ();
+ foreach my $Path (@SysHeaders)
+ {
+ if(my $Skip = $SysCInfo->{"skip_headers"})
+ { # do NOT search for some headers
+ if(check_list($Path, $Skip)) {
+ next;
+ }
+ }
+ $SysLib_SysHeaders{$Path}{$Path} = 1;
+ }
+ if($CheckHeadersOnly) {
+ writeFile($SYS_DUMP_PATH."/mode.txt", "headers-only");
+ }
+ else {
+ writeFile($SYS_DUMP_PATH."/mode.txt", "group-by-headers");
+ }
+ }
+ @SysHeaders = ();# clear memory
+ my (%Skipped, %Failed, %Success) = ();
+ printMsg("INFO", "Generating XML descriptors ...");
+ foreach my $LRelPath (keys(%SysLib_SysHeaders))
+ {
+ my $LName = get_filename($LRelPath);
+ my $DPath = $SYS_DUMP_PATH."/descriptors/$LName.xml";
+ unlink($DPath);
+ if(my @LibHeaders = keys(%{$SysLib_SysHeaders{$LRelPath}}))
+ {
+ my $LSName = parse_libname($LName, "short", $OStarget);
+ if($GroupByHeaders)
+ { # header short name
+ $LSName = $LName;
+ $LSName=~s/\.(.+?)\Z//;
+ }
+ my (%DirsHeaders, %Includes) = ();
+ foreach my $HRelPath (@LibHeaders) {
+ $DirsHeaders{get_dirname($HRelPath)}{$HRelPath}=1;
+ }
+ foreach my $Dir (keys(%DirsHeaders))
+ {
+ my $DirPart = 0;
+ my $TotalHeaders = keys(%{$SysHeaderDir_SysHeaders{$Dir}});
+ if($TotalHeaders) {
+ $DirPart = (keys(%{$DirsHeaders{$Dir}})*100)/$TotalHeaders;
+ }
+ my $Neighbourhoods = keys(%{$SysHeaderDir_SysLibs{$Dir}});
+ if($Neighbourhoods==1)
+ { # one lib in this directory
+ if(get_filename($Dir) ne "include"
+ and $DirPart>=5)
+ { # complete directory
+ $Includes{$Dir} = 1;
+ }
+ else
+ { # list of headers
+ @Includes{keys(%{$DirsHeaders{$Dir}})}=values(%{$DirsHeaders{$Dir}});
+ }
+ }
+ elsif((keys(%{$DirsHeaders{$Dir}})*100)/($#LibHeaders+1)>5)
+ {# remove 5% divergence
+ if(get_filename($Dir) ne "include"
+ and $DirPart>=50)
+ { # complete directory
+ $Includes{$Dir} = 1;
+ }
+ else
+ { # list of headers
+ @Includes{keys(%{$DirsHeaders{$Dir}})}=values(%{$DirsHeaders{$Dir}});
+ }
+ }
+ }
+ if($GroupByHeaders)
+ { # one header in one ABI dump
+ %Includes = ($LibHeaders[0] => 1);
+ }
+ my $LVersion = $SysLibVersion{$LName};
+ if($LVersion)
+ {# append by system name
+ $LVersion .= "-".$SysDescriptor{"Name"};
+ }
+ else {
+ $LVersion = $SysDescriptor{"Name"};
+ }
+ my @Content = ("<version>\n $LVersion\n</version>");
+ my @IncHeaders = sort {natural_sorting($a, $b)} keys(%Includes);
+ sort_by_word(\@IncHeaders, parse_libname($LName, "shortest", $OStarget));
+ if(is_abs($IncHeaders[0])) {
+ push(@Content, "<headers>\n ".join("\n ", @IncHeaders)."\n</headers>");
+ }
+ else {
+ push(@Content, "<headers>\n {RELPATH}/".join("\n {RELPATH}/", @IncHeaders)."\n</headers>");
+ }
+ if($GroupByHeaders)
+ {
+ if($SysDescriptor{"Image"}) {
+ push(@Content, "<libs>\n ".$SysDescriptor{"Image"}."\n</libs>");
+ }
+ }
+ else
+ {
+ if(is_abs($LRelPath) or -f $LRelPath) {
+ push(@Content, "<libs>\n $LRelPath\n</libs>");
+ }
+ else {
+ push(@Content, "<libs>\n {RELPATH}/$LRelPath\n</libs>");
+ }
+ }
+ if(my @SearchHeaders = keys(%{$SysDescriptor{"SearchHeaders"}})) {
+ push(@Content, "<search_headers>\n ".join("\n ", @SearchHeaders)."\n</search_headers>");
+ }
+ if(my @SearchLibs = keys(%{$SysDescriptor{"SearchLibs"}})) {
+ push(@Content, "<search_libs>\n ".join("\n ", @SearchLibs)."\n</search_libs>");
+ }
+ if(my @Tools = keys(%{$SysDescriptor{"Tools"}})) {
+ push(@Content, "<tools>\n ".join("\n ", @Tools)."\n</tools>");
+ }
+ my @Skip = ();
+ if($SysInfo->{$LSName}{"skip_headers"}) {
+ @Skip = (@Skip, @{$SysInfo->{$LSName}{"skip_headers"}});
+ }
+ if($SysCInfo->{"skip_headers"}) {
+ @Skip = (@Skip, @{$SysCInfo->{"skip_headers"}});
+ }
+ if($SysInfo->{$LSName}{"non_self_compiled"}) {
+ @Skip = (@Skip, @{$SysInfo->{$LSName}{"non_self_compiled"}});
+ }
+ if($SkipDHeaders{$LSName}) {
+ @Skip = (@Skip, @{$SkipDHeaders{$LSName}});
+ }
+ if(@Skip) {
+ push(@Content, "<skip_headers>\n ".join("\n ", @Skip)."\n</skip_headers>");
+ }
+ if($SysInfo->{$LSName}{"add_include_paths"}) {
+ push(@Content, "<add_include_paths>\n ".join("\n ", @{$SysInfo->{$LSName}{"add_include_paths"}})."\n</add_include_paths>");
+ }
+ if($SysInfo->{$LSName}{"skip_types"}) {
+ push(@Content, "<skip_types>\n ".join("\n ", @{$SysInfo->{$LSName}{"skip_types"}})."\n</skip_types>");
+ }
+ my @SkipSymb = ();
+ if($SysInfo->{$LSName}{"skip_symbols"}) {
+ push(@SkipSymb, @{$SysInfo->{$LSName}{"skip_symbols"}});
+ }
+ if($SysCInfo->{"skip_symbols"}) {
+ push(@SkipSymb, @{$SysCInfo->{"skip_symbols"}});
+ }
+ if(@SkipSymb) {
+ push(@Content, "<skip_symbols>\n ".join("\n ", @SkipSymb)."\n</skip_symbols>");
+ }
+ my @Preamble = ();
+ if($SysCInfo->{"include_preamble"}) {
+ push(@Preamble, @{$SysCInfo->{"include_preamble"}});
+ }
+ if($LSName=~/\AlibX\w+\Z/)
+ { # add Xlib.h for libXt, libXaw, libXext and others
+ push(@Preamble, "Xlib.h", "X11/Intrinsic.h");
+ }
+ if($SysInfo->{$LSName}{"include_preamble"}) {
+ push(@Preamble, @{$SysInfo->{$LSName}{"include_preamble"}});
+ }
+ if(@Preamble) {
+ push(@Content, "<include_preamble>\n ".join("\n ", @Preamble)."\n</include_preamble>");
+ }
+ my @Defines = ();
+ if($SysCInfo->{"defines"}) {
+ push(@Defines, $SysCInfo->{"defines"});
+ }
+ if($SysInfo->{$LSName}{"defines"}) {
+ push(@Defines, $SysInfo->{$LSName}{"defines"});
+ }
+ if($SysDescriptor{"Defines"}) {
+ push(@Defines, $SysDescriptor{"Defines"});
+ }
+ if(@Defines) {
+ push(@Content, "<defines>\n ".join("\n ", @Defines)."\n</defines>");
+ }
+ my @CompilerOpts = ();
+ if($SysCInfo->{"gcc_options"}) {
+ push(@CompilerOpts, @{$SysCInfo->{"gcc_options"}});
+ }
+ if($SysInfo->{$LSName}{"gcc_options"}) {
+ push(@CompilerOpts, @{$SysInfo->{$LSName}{"gcc_options"}});
+ }
+ if(@CompilerOpts) {
+ push(@Content, "<gcc_options>\n ".join("\n ", @CompilerOpts)."\n</gcc_options>");
+ }
+ if($SysDescriptor{"CrossPrefix"}) {
+ push(@Content, "<cross_prefix>\n ".$SysDescriptor{"CrossPrefix"}."\n</cross_prefix>");
+ }
+ writeFile($DPath, join("\n\n", @Content));
+ $Success{$LRelPath}=1;
+ }
+ }
+ printMsg("INFO", "Dumping ABIs:");
+ my %DumpSuccess = ();
+ my @Descriptors = cmd_find($SYS_DUMP_PATH."/descriptors","f","*.xml","1");
+ foreach my $DPath (sort {lc($a) cmp lc($b)} @Descriptors)
+ {
+ my $DName = get_filename($DPath);
+ my $LName = "";
+ if($DName=~/\A(.+).xml\Z/) {
+ $LName = $1;
+ }
+ else {
+ next;
+ }
+ if(not is_target_lib($LName)
+ and not is_target_lib($LibSoname{$LName})) {
+ next;
+ }
+ $DPath = cut_path_prefix($DPath, $ORIG_DIR);
+ my $ACC_dump = "perl $0";
+ if($GroupByHeaders)
+ { # header name is going here
+ $ACC_dump .= " -l $LName";
+ }
+ else {
+ $ACC_dump .= " -l ".parse_libname($LName, "name", $OStarget);
+ }
+ $ACC_dump .= " -dump \"$DPath\"";
+ if($SystemRoot)
+ {
+ $ACC_dump .= " -relpath \"$SystemRoot\"";
+ $ACC_dump .= " -sysroot \"$SystemRoot\"";
+ }
+ my $DumpPath = "$SYS_DUMP_PATH/abi_dumps/$LName.abi.".getAR_EXT($OSgroup);
+ $ACC_dump .= " -dump-path \"$DumpPath\"";
+ my $LogPath = "$SYS_DUMP_PATH/logs/$LName.txt";
+ unlink($LogPath);
+ $ACC_dump .= " -log-path \"$LogPath\"";
+ if($CrossGcc) {
+ $ACC_dump .= " -cross-gcc \"$CrossGcc\"";
+ }
+ if($CheckHeadersOnly) {
+ $ACC_dump .= " -headers-only";
+ }
+ if($UseStaticLibs) {
+ $ACC_dump .= " -static-libs";
+ }
+ if($GroupByHeaders) {
+ $ACC_dump .= " -header $LName";
+ }
+ if($NoStdInc
+ or $OStarget=~/windows|symbian/)
+ { # 1. user-defined
+ # 2. windows/minGW
+ # 3. symbian/GCC
+ $ACC_dump .= " -nostdinc";
+ }
+ if($Quiet)
+ { # quiet mode
+ $ACC_dump .= " -quiet";
+ }
+ if($LogMode eq "n") {
+ $ACC_dump .= " -logging-mode n";
+ }
+ elsif($Quiet) {
+ $ACC_dump .= " -logging-mode a";
+ }
+ if($Debug)
+ { # debug mode
+ $ACC_dump .= " -debug";
+ printMsg("INFO", "$ACC_dump");
+ }
+ printMsg("INFO_C", "Dumping $LName: ");
+ system($ACC_dump." 1>$TMP_DIR/null 2>$TMP_DIR/$LName.stderr");
+ appendFile("$SYS_DUMP_PATH/logs/$LName.txt", "The ACC parameters:\n $ACC_dump\n");
+ if(-s "$TMP_DIR/$LName.stderr")
+ {
+ appendFile("$SYS_DUMP_PATH/logs/$LName.txt", readFile("$TMP_DIR/$LName.stderr"));
+ if(get_CoreError($?>>8) eq "Invalid_Dump") {
+ printMsg("INFO", "Empty");
+ }
+ else {
+ printMsg("INFO", "Failed (\'$SYS_DUMP_PATH/logs/$LName.txt\')");
+ }
+ }
+ elsif(not -f $DumpPath) {
+ printMsg("INFO", "Failed (\'$SYS_DUMP_PATH/logs/$LName.txt\')");
+ }
+ else
+ {
+ $DumpSuccess{$LName}=1;
+ printMsg("INFO", "Ok");
+ }
+ }
+ if(not $GroupByHeaders)
+ { # general mode
+ printMsg("INFO", "Total libraries: ".keys(%TotalLibs));
+ printMsg("INFO", "Skipped libraries: ".keys(%Skipped)." ($SYS_DUMP_PATH/skipped.txt)");
+ printMsg("INFO", "Failed to find headers: ".keys(%Failed)." ($SYS_DUMP_PATH/failed.txt)");
+ }
+ printMsg("INFO", "Created descriptors: ".keys(%Success)." ($SYS_DUMP_PATH/descriptors/)");
+ printMsg("INFO", "Dumped ABIs: ".keys(%DumpSuccess)." ($SYS_DUMP_PATH/abi_dumps/)");
+ printMsg("INFO", "The ".$SysDescriptor{"Name"}." system ABI has been dumped to:\n $SYS_DUMP_PATH");
+}
+
+return 1; \ No newline at end of file