From ca57fd4d8b854d97bd70efcf1018e34bc2ad4981 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 12 Aug 2013 17:11:41 +0200 Subject: use the 'abi-complicance-checker package instead of using the buildin copy for the abi checks --- abicheck/abi-compliance-checker.pl | 7325 ------------------------------------ abicheck/run_abi_test | 7 +- 2 files changed, 6 insertions(+), 7326 deletions(-) delete mode 100644 abicheck/abi-compliance-checker.pl diff --git a/abicheck/abi-compliance-checker.pl b/abicheck/abi-compliance-checker.pl deleted file mode 100644 index 7fd8ab173..000000000 --- a/abicheck/abi-compliance-checker.pl +++ /dev/null @@ -1,7325 +0,0 @@ -#!/usr/bin/perl -########################################################################### -# ABI-compliance-checker v1.13, lightweight tool for statically checking -# backward binary compatibility of shared C/C++ libraries in Linux. -# Copyright (C) The Linux Foundation -# Copyright (C) Institute for System Programming, RAS -# Author: Andrey Ponomarenko -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# -# 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 -# along with this program. If not, see . -########################################################################### -use Getopt::Long; -Getopt::Long::Configure ("posix_default", "no_ignore_case"); -use Data::Dumper; - -my $ABI_COMPLIANCE_CHECKER_VERSION = "1.13"; -my ($Help, $ShowVersion, %Descriptor, $TargetLibraryName, $HeaderCheckingMode_Separately, $GenerateDescriptor, $TestSystem, $DumpInfo_DescriptorPath, $CheckHeadersOnly, $InterfacesListPath, $AppPath, $ShowExpendTime); - -my $CmdName = get_FileName($0); -GetOptions("h|help!" => \$Help, - "v|version!" => \$ShowVersion, -#general options - "l|library=s" => \$TargetLibraryName, - "d1|descriptor1=s" => \$Descriptor{1}{"Path"}, - "d2|descriptor2=s" => \$Descriptor{2}{"Path"}, -#extra options - "app|application=s" => \$AppPath, - "symbols_list|int_list=s" => \$InterfacesListPath, - "dump_abi|dump_info=s" => \$DumpInfo_DescriptorPath, - "headers_only!" => \$CheckHeadersOnly, -#other options - "d|descriptor_template!" => \$GenerateDescriptor, - "separately!" => \$HeaderCheckingMode_Separately, - "test!" => \$TestSystem, - "time!" => \$ShowExpendTime -) or exit(1); - -sub HELP_MESSAGE() -{ - print STDERR <<"EOM" - -NAME: - $CmdName - check ABI compatibility of shared C/C++ library versions - -DESCRIPTION: - Lightweight tool for statically checking backward binary compatibility of shared C/C++ libraries - in Linux. It checks header files along with shared objects in two library versions and searches - for ABI changes that may lead to incompatibility. Breakage of the binary compatibility may result - in crashing or incorrect behavior of applications built with an old version of a library when - it is running with a new one. - - ABI Compliance Checker was intended for library developers that are interested in ensuring - backward binary compatibility. Also it can be used for checking forward binary compatibility - and checking applications portability to the new library version. - - This tool is free software: you can redistribute it and/or modify it under the terms of the GNU GPL. - -USAGE: - $CmdName [options] - -EXAMPLE OF USE: - $CmdName -l -d1 <1st_version_descriptor> -d2 <2nd_version_descriptor> - -GENERAL OPTIONS: - -h|-help - Print this help. - - -v|-version - Print version. - - -l|-library - Library name (without version). - It affects only on the path and the title of the report. - - -d1|-descriptor1 - Path to descriptor of 1st library version. - - -d2|-descriptor2 - Path to descriptor of 2nd library version. - -EXTRA OPTIONS: - -app|-application - This option allow to specify the application that should be tested for portability - to the new library version. - - -dump_abi|-dump_info - Dump library ABI information using specified descriptor. - This command will create '_.abi.tar.gz' file in the directory 'abi_dumps//'. - You can transfer it anywhere and pass instead of library descriptor. - - -headers_only - Check header files without shared objects. It is easy to run, but may provide - a low quality ABI compliance report with false positives and without - detecting of added/withdrawn interfaces. - - -symbols_list|-int_list - This option allow to specify a file with a list of interfaces (mangled names in C++) - that should be checked, other library interfaces will not be checked. - -OTHER OPTIONS: - -d|-descriptor_template - Create library descriptor template 'library-descriptor.xml' in the current directory. - - -separately - Check headers individually. This mode requires more time for checking ABI compliance, - but possible compiler errors in one header can't affect others. - - -test - Run internal tests (create two binary-incompatible versions of an artificial library - and run ABI-Compliance-Checker on it). - -DESCRIPTOR EXAMPLE: - - 1.28.0 - - - - /usr/local/atk/atk-1.28.0/include/ - - - - /usr/local/atk/atk-1.28.0/lib/libatk-1.0.so - - - - /usr/include/glib-2.0/ - /usr/lib/glib-2.0/include/ - - - -Report bugs to -For more information, please see: http://ispras.linux-foundation.org/index.php/ABI_compliance_checker -EOM - ; -} - -my $Descriptor_Template = " - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"; - -my %Operator_Indication = ( -"not" => "~", -"assign" => "=", -"andassign" => "&=", -"orassign" => "|=", -"xorassign" => "^=", -"or" => "|", -"xor" => "^", -"addr" => "&", -"and" => "&", -"lnot" => "!", -"eq" => "==", -"ne" => "!=", -"lt" => "<", -"lshift" => "<<", -"lshiftassign" => "<<=", -"rshiftassign" => ">>=", -"call" => "()", -"mod" => "%", -"modassign" => "%=", -"subs" => "[]", -"land" => "&&", -"lor" => "||", -"rshift" => ">>", -"ref" => "->", -"le" => "<=", -"deref" => "*", -"mult" => "*", -"preinc" => "++", -"delete" => " delete", -"vecnew" => " new[]", -"vecdelete" => " delete[]", -"predec" => "--", -"postinc" => "++", -"postdec" => "--", -"plusassign" => "+=", -"plus" => "+", -"minus" => "-", -"minusassign" => "-=", -"gt" => ">", -"ge" => ">=", -"new" => " new", -"multassign" => "*=", -"divassign" => "/=", -"div" => "/", -"neg" => "-", -"pos" => "+", -"memref" => "->*", -"compound" => "," -); - -sub num_to_str($) -{ - my $Number = $_[0]; - if(int($Number)>3) - { - return $Number."th"; - } - elsif(int($Number)==1) - { - return "1st"; - } - elsif(int($Number)==2) - { - return "2nd"; - } - elsif(int($Number)==3) - { - return "3rd"; - } - else - { - return ""; - } -} - -#Global variables -my $REPORT_PATH; -my %ERR_PATH; -my $POINTER_SIZE; -my $MAX_COMMAND_LINE_ARGUMENTS = 4096; -my %Cache; -my %FuncAttr; -my %LibInfo; -my %HeaderCompileError; -my $StartTime; -my %CompilerOptions; -my %AddedInt; -my %WithdrawnInt; -my @RecurLib; -my %CheckedSoLib; - -#Constants checking -my %ConstantsSrc; -my %Constants; - -#Types -my %TypeDescr; -my %TemplateInstance_Func; -my %TemplateInstance; -my %OpaqueTypes; -my %Tid_TDid; -my %CheckedTypes; -my %Typedef_BaseName; -my %StdCxxTypedef; -my %TName_Tid; -my %EnumMembName_Id; - -#Interfaces -my %FuncDescr; -my %ClassFunc; -my %ClassVirtFunc; -my %ClassIdVirtFunc; -my %ClassId; -my %tr_name; -my %mangled_name; -my %InternalInterfaces; -my %InterfacesList; -my %InterfacesList_App; -my %CheckedInterfaces; -my %DepInterfaces; - -#Headers -my %Include_Preamble; -my %Headers; -my %HeaderName_Destinations; -my %Header_Dependency; - -#Shared objects -my %SoLib_DefaultPath; - -#Merging -my %CompleteSignature; -my @RecurTypes; -my %Interface_Library; -my %Library_Interface; -my %Language; -my %SoNames_All; -my $Version; - -#Symbols versioning -my %SymVer; - -#Problem descriptions -my %CompatProblems; -my %ConstantProblems; - -#Rerorts -my $ContentID = 1; -my $ContentSpanStart = "\n"; -my $ContentSpanEnd = "\n"; -my $ContentDivStart = "
\n"; -my $ContentDivEnd = "
\n"; -my $Content_Counter = 0; - -sub readDescriptor($) -{ - my $LibVersion = $_[0]; - if(not -e $Descriptor{$LibVersion}{"Path"}) - { - return; - } - my $Descriptor_File = readFile($Descriptor{$LibVersion}{"Path"}); - $Descriptor_File =~ s/\/\*(.|\n)+?\*\///g; - $Descriptor_File =~ s/<\!--(.|\n)+?-->//g; - if(not $Descriptor_File) - { - print "ERROR: descriptor d$LibVersion is empty\n"; - exit(1); - } - $Descriptor{$LibVersion}{"Version"} = parseTag(\$Descriptor_File, "version"); - if(not $Descriptor{$LibVersion}{"Version"}) - { - print "ERROR: version in the descriptor d$LibVersion was not specified (section )\n\n"; - exit(1); - } - $Descriptor{$LibVersion}{"Headers"} = parseTag(\$Descriptor_File, "headers"); - if(not $Descriptor{$LibVersion}{"Headers"}) - { - print "ERROR: header files in the descriptor d$LibVersion were not specified (section )\n"; - exit(1); - } - if(not $CheckHeadersOnly) - { - $Descriptor{$LibVersion}{"Libs"} = parseTag(\$Descriptor_File, "libs"); - if(not $Descriptor{$LibVersion}{"Libs"}) - { - print "ERROR: shared objects in the descriptor d$LibVersion were not specified (section )\n"; - exit(1); - } - } - $Descriptor{$LibVersion}{"Include_Paths"} = parseTag(\$Descriptor_File, "include_paths"); - $Descriptor{$LibVersion}{"Gcc_Options"} = parseTag(\$Descriptor_File, "gcc_options"); - foreach my $Option (split("\n", $Descriptor{$LibVersion}{"Gcc_Options"})) - { - $Option =~ s/\A\s+|\s+\Z//g; - next if(not $Option); - $CompilerOptions{$LibVersion} .= " ".$Option; - } - $Descriptor{$LibVersion}{"Opaque_Types"} = parseTag(\$Descriptor_File, "opaque_types"); - foreach my $Type_Name (split("\n", $Descriptor{$LibVersion}{"Opaque_Types"})) - { - $Type_Name =~ s/\A\s+|\s+\Z//g; - next if(not $Type_Name); - $OpaqueTypes{$LibVersion}{$Type_Name} = 1; - } - $Descriptor{$LibVersion}{"Skip_interfaces"} = parseTag(\$Descriptor_File, "skip_interfaces"); - foreach my $Interface_Name (split("\n", $Descriptor{$LibVersion}{"Skip_interfaces"})) - { - $Interface_Name =~ s/\A\s+|\s+\Z//g; - next if(not $Interface_Name); - $InternalInterfaces{$LibVersion}{$Interface_Name} = 1; - } - $Descriptor{$LibVersion}{"Include_Preamble"} = parseTag(\$Descriptor_File, "include_preamble"); - my $Position = 0; - foreach my $Header_Name (split("\n", $Descriptor{$LibVersion}{"Include_Preamble"})) - { - $Header_Name =~ s/\A\s+|\s+\Z//g; - next if(not $Header_Name); - $Include_Preamble{$LibVersion}{$Header_Name}{"Position"} = $Position; - $Position+=1; - } - my $Descriptors_Dir = "descriptors_storage/$TargetLibraryName"; - system("mkdir", "-p", $Descriptors_Dir); - my $Descriptor_Name = $TargetLibraryName."_".$Descriptor{$LibVersion}{"Version"}.".desc"; - if($Descriptor{$LibVersion}{"Path"} ne $Descriptors_Dir."/".$Descriptor_Name) - { - system("cp", "-f", $Descriptor{$LibVersion}{"Path"}, $Descriptors_Dir."/".$Descriptor_Name); - } - $ERR_PATH{$LibVersion} = "header_compile_errors/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}; -} - -sub parseTag($$) -{ - my ($CodeRef, $Tag) = @_; - return "" if(not $CodeRef or not ${$CodeRef} or not $Tag); - if(${$CodeRef} =~ s/\<$Tag\>((.|\n)+?)\<\/$Tag\>//) - { - my $Content = $1; - $Content=~s/(\A\s+|\s+\Z)//g; - return $Content; - } - else - { - return ""; - } -} - -my %check_node=( -"array_type"=>1, -"binfo"=>1, -"boolean_type"=>1, -"complex_type"=>1, -"const_decl"=>1, -"enumeral_type"=>1, -"field_decl"=>1, -"function_decl"=>1, -"function_type"=>1, -"identifier_node"=>1, -"integer_cst"=>1, -"integer_type"=>1, -"method_type"=>1, -"namespace_decl"=>1, -"parm_decl"=>1, -"pointer_type"=>1, -"real_cst"=>1, -"real_type"=>1, -"record_type"=>1, -"reference_type"=>1, -"string_cst"=>1, -"template_decl"=>1, -"template_type_parm"=>1, -"tree_list"=>1, -"tree_vec"=>1, -"type_decl"=>1, -"union_type"=>1, -"var_decl"=>1, -"void_type"=>1); - -sub getInfo($) -{ - my $InfoPath = $_[0]; - return if(not $InfoPath or not -f $InfoPath); - my $InfoPath_New = $InfoPath.".1"; - #my $Keywords = join("\\|", keys(%check_node));#|grep "$Keywords" - system("sed ':a;N;\$!ba;s/\\n[^\@]//g' ".esc($InfoPath)."|sed 's/ [ ]\\+/ /g' > ".esc($InfoPath_New)); - system("rm", "-fr", $InfoPath); - #getting info - open(INFO, $InfoPath_New) || die ("can't open file '\$InfoPath_New\': $!\n"); - while() - { - chomp; - if(/\A@([0-9]+)[ ]+([a-zA-Z_]+)[ ]+(.*)\Z/) - { - next if(not $check_node{$2}); - $LibInfo{$Version}{$1}{"info_type"}=$2; - $LibInfo{$Version}{$1}{"info"}=$3; - } - } - close(INFO); - system("rm", "-fr", $InfoPath_New); - #processing info - setTemplateParams_All(); - getTypeDescr_All(); - getFuncDescr_All(); - getVarDescr_All(); - %LibInfo = (); - %TemplateInstance = (); -} - -sub setTemplateParams_All() -{ - foreach (keys(%{$LibInfo{$Version}})) - { - if($LibInfo{$Version}{$_}{"info_type"} eq "template_decl") - { - setTemplateParams($_); - } - } -} - -sub setTemplateParams($) -{ - my $TypeInfoId = $_[0]; - my $Info = $LibInfo{$Version}{$TypeInfoId}{"info"}; - if($Info =~ /(inst|spcs)[ ]*:[ ]*@([0-9]+) /) - { - my $TmplInst_InfoId = $2; - setTemplateInstParams($TmplInst_InfoId); - my $TmplInst_Info = $LibInfo{$Version}{$TmplInst_InfoId}{"info"}; - while($TmplInst_Info =~ /chan[ ]*:[ ]*@([0-9]+) /) - { - $TmplInst_InfoId = $1; - $TmplInst_Info = $LibInfo{$Version}{$TmplInst_InfoId}{"info"}; - setTemplateInstParams($TmplInst_InfoId); - } - } -} - -sub setTemplateInstParams($) -{ - my $TmplInst_Id = $_[0]; - my $Info = $LibInfo{$Version}{$TmplInst_Id}{"info"}; - my ($Params_InfoId, $ElemId) = (); - if($Info =~ /purp[ ]*:[ ]*@([0-9]+) /) - { - $Params_InfoId = $1; - } - if($Info =~ /valu[ ]*:[ ]*@([0-9]+) /) - { - $ElemId = $1; - } - if($Params_InfoId and $ElemId) - { - my $Params_Info = $LibInfo{$Version}{$Params_InfoId}{"info"}; - while($Params_Info =~ s/ ([0-9]+)[ ]*:[ ]*@([0-9]+) //) - { - my ($Param_Pos, $Param_TypeId) = ($1, $2); - return if($LibInfo{$Version}{$Param_TypeId}{"info_type"} eq "template_type_parm"); - if($LibInfo{$ElemId}{"info_type"} eq "function_decl") - { - $TemplateInstance_Func{$Version}{$ElemId}{$Param_Pos} = $Param_TypeId; - } - else - { - $TemplateInstance{$Version}{getTypeDeclId($ElemId)}{$ElemId}{$Param_Pos} = $Param_TypeId; - } - } - } -} - -sub getTypeDeclId($) -{ - my $TypeInfo = $LibInfo{$Version}{$_[0]}{"info"}; - if($TypeInfo =~ /name[ ]*:[ ]*@([0-9]+)/) - { - return $1; - } - else - { - return ""; - } -} - -sub isFuncPtr($) -{ - my $Ptd = pointTo($_[0]); - if($Ptd) - { - if(($LibInfo{$Version}{$_[0]}{"info"} =~ m/unql[ ]*:/) and not ($LibInfo{$Version}{$_[0]}{"info"} =~ m/qual[ ]*:/)) - { - return 0; - } - elsif(($LibInfo{$Version}{$_[0]}{"info_type"} eq "pointer_type") and ($LibInfo{$Version}{$Ptd}{"info_type"} eq "function_type" or $LibInfo{$Version}{$Ptd}{"info_type"} eq "method_type")) - { - return 1; - } - else - { - return 0; - } - } - else - { - return 0; - } -} - -sub pointTo($) -{ - my $TypeInfo = $LibInfo{$Version}{$_[0]}{"info"}; - if($TypeInfo =~ /ptd[ ]*:[ ]*@([0-9]+)/) - { - return $1; - } - else - { - return ""; - } -} - -sub getTypeDescr_All() -{ - foreach (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}})) - { - if($LibInfo{$Version}{$_}{"info_type"}=~/_type\Z/ and $LibInfo{$Version}{$_}{"info_type"}!~/function_type|method_type/) - { - getTypeDescr(getTypeDeclId($_), $_); - } - } - $TypeDescr{$Version}{""}{-1}{"Name"} = "..."; - $TypeDescr{$Version}{""}{-1}{"Type"} = "Intrinsic"; - $TypeDescr{$Version}{""}{-1}{"Tid"} = -1; -} - -sub getTypeDescr($$) -{ - my ($TypeDeclId, $TypeId) = @_; - $Tid_TDid{$Version}{$TypeId} = $TypeDeclId; - %{$TypeDescr{$Version}{$TypeDeclId}{$TypeId}} = getTypeAttr($TypeDeclId, $TypeId); - if(not $TypeDescr{$Version}{$TypeDeclId}{$TypeId}{"Name"}) - { - delete($TypeDescr{$Version}{$TypeDeclId}{$TypeId}); - return; - } - if(not $TName_Tid{$Version}{$TypeDescr{$Version}{$TypeDeclId}{$TypeId}{"Name"}}) - { - $TName_Tid{$Version}{$TypeDescr{$Version}{$TypeDeclId}{$TypeId}{"Name"}} = $TypeId; - } -} - -sub getTypeAttr($$) -{ - my ($TypeDeclId, $TypeId) = @_; - my ($BaseTypeSpec, %TypeAttr) = (); - if($TypeDescr{$Version}{$TypeDeclId}{$TypeId}{"Name"}) - { - return %{$TypeDescr{$Version}{$TypeDeclId}{$TypeId}}; - } - $TypeAttr{"Tid"} = $TypeId; - $TypeAttr{"TDid"} = $TypeDeclId; - $TypeAttr{"Type"} = getTypeType($TypeDeclId, $TypeId); - if($TypeAttr{"Type"} eq "Unknown") - { - return (); - } - elsif($TypeAttr{"Type"} eq "FuncPtr") - { - %{$TypeDescr{$Version}{$TypeDeclId}{$TypeId}} = getFuncPtrAttr(pointTo($TypeId), $TypeDeclId, $TypeId); - $TName_Tid{$Version}{$TypeDescr{$Version}{$TypeDeclId}{$TypeId}{"Name"}} = $TypeId; - return %{$TypeDescr{$Version}{$TypeDeclId}{$TypeId}}; - } - elsif($TypeAttr{"Type"} eq "Array") - { - ($TypeAttr{"BaseType"}{"Tid"}, $TypeAttr{"BaseType"}{"TDid"}, $BaseTypeSpec) = selectBaseType($TypeDeclId, $TypeId); - my %BaseTypeAttr = getTypeAttr($TypeAttr{"BaseType"}{"TDid"}, $TypeAttr{"BaseType"}{"Tid"}); - my $ArrayElemNum = getSize($TypeId)/8; - $ArrayElemNum = $ArrayElemNum/$BaseTypeAttr{"Size"} if($BaseTypeAttr{"Size"}); - $TypeAttr{"Size"} = $ArrayElemNum; - if($ArrayElemNum) - { - $TypeAttr{"Name"} = $BaseTypeAttr{"Name"}."[".$ArrayElemNum."]"; - } - else - { - $TypeAttr{"Name"} = $BaseTypeAttr{"Name"}."[]"; - } - $TypeAttr{"Name"} = correctName($TypeAttr{"Name"}); - $TypeAttr{"Library"} = $BaseTypeAttr{"Library"}; - $TypeAttr{"Header"} = $BaseTypeAttr{"Header"}; - %{$TypeDescr{$Version}{$TypeDeclId}{$TypeId}} = %TypeAttr; - $TName_Tid{$Version}{$TypeDescr{$Version}{$TypeDeclId}{$TypeId}{"Name"}} = $TypeId; - return %TypeAttr; - } - elsif($TypeAttr{"Type"} =~ /Intrinsic|Union|Struct|Enum|Class/) - { - if($TemplateInstance{$Version}{$TypeDeclId}{$TypeId}) - { - my @Template_Params = (); - foreach my $Param_Pos (sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$TypeDeclId}{$TypeId}})) - { - my $Type_Id = $TemplateInstance{$Version}{$TypeDeclId}{$TypeId}{$Param_Pos}; - my $Param = get_TemplateParam($Type_Id); - if($Param eq "") - { - return (); - } - @Template_Params = (@Template_Params, $Param); - } - %{$TypeDescr{$Version}{$TypeDeclId}{$TypeId}} = getTrivialTypeAttr($TypeDeclId, $TypeId); - $TypeDescr{$Version}{$TypeDeclId}{$TypeId}{"Name"} = $TypeDescr{$Version}{$TypeDeclId}{$TypeId}{"Name"}."< ".join(", ", @Template_Params)." >"; - $TypeDescr{$Version}{$TypeDeclId}{$TypeId}{"Name"} = correctName($TypeDescr{$Version}{$TypeDeclId}{$TypeId}{"Name"}); - $TName_Tid{$Version}{$TypeDescr{$Version}{$TypeDeclId}{$TypeId}{"Name"}} = $TypeId; - return %{$TypeDescr{$Version}{$TypeDeclId}{$TypeId}}; - } - else - { - %{$TypeDescr{$Version}{$TypeDeclId}{$TypeId}} = getTrivialTypeAttr($TypeDeclId, $TypeId); - return %{$TypeDescr{$Version}{$TypeDeclId}{$TypeId}}; - } - } - else - { - ($TypeAttr{"BaseType"}{"Tid"}, $TypeAttr{"BaseType"}{"TDid"}, $BaseTypeSpec) = selectBaseType($TypeDeclId, $TypeId); - my %BaseTypeAttr = getTypeAttr($TypeAttr{"BaseType"}{"TDid"}, $TypeAttr{"BaseType"}{"Tid"}); - if($BaseTypeSpec and $BaseTypeAttr{"Name"}) - { - if(($TypeAttr{"Type"} eq "Pointer") and $BaseTypeAttr{"Name"}=~/\([\*]+\)/) - { - $TypeAttr{"Name"} = $BaseTypeAttr{"Name"}; - $TypeAttr{"Name"} =~ s/\(([*]+)\)/($1*)/g; - } - else - { - $TypeAttr{"Name"} = $BaseTypeAttr{"Name"}." ".$BaseTypeSpec; - } - } - elsif($BaseTypeAttr{"Name"}) - { - $TypeAttr{"Name"} = $BaseTypeAttr{"Name"}; - } - if($TypeAttr{"Type"} eq "Typedef") - { - $TypeAttr{"Name"} = getNameByInfo($TypeDeclId); - $TypeAttr{"NameSpace"} = getNameSpace($TypeDeclId); - if($TypeAttr{"NameSpace"}) - { - $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"}; - } - ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId); - if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BaseTypeAttr{"NameSpace"}=~/\Astd(::|\Z)/) - { - $StdCxxTypedef{$Version}{$BaseTypeAttr{"Name"}} = $TypeAttr{"Name"}; - } - $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BaseTypeAttr{"Name"}; - } - if(not $TypeAttr{"Size"}) - { - if($TypeAttr{"Type"} eq "Pointer") - { - $TypeAttr{"Size"} = $POINTER_SIZE; - } - else - { - $TypeAttr{"Size"} = $BaseTypeAttr{"Size"}; - } - } - $TypeAttr{"Name"} = correctName($TypeAttr{"Name"}); - $TypeAttr{"Library"} = $BaseTypeAttr{"Library"}; - $TypeAttr{"Header"} = $BaseTypeAttr{"Header"} if(not $TypeAttr{"Header"}); - %{$TypeDescr{$Version}{$TypeDeclId}{$TypeId}} = %TypeAttr; - $TName_Tid{$Version}{$TypeDescr{$Version}{$TypeDeclId}{$TypeId}{"Name"}} = $TypeId; - return %TypeAttr; - } -} - -sub get_TemplateParam($) -{ - my $Type_Id = $_[0]; - if(getNodeType($Type_Id) eq "integer_cst") - { - return getNodeIntCst($Type_Id); - } - elsif(getNodeType($Type_Id) eq "string_cst") - { - return getNodeStrCst($Type_Id); - } - else - { - my $Type_DId = getTypeDeclId($Type_Id); - my %ParamAttr = getTypeAttr($Type_DId, $Type_Id); - if(not $ParamAttr{"Name"}) - { - return ""; - } - if($ParamAttr{"Name"}=~/\>/) - { - if($StdCxxTypedef{$Version}{$ParamAttr{"Name"}}) - { - return $StdCxxTypedef{$Version}{$ParamAttr{"Name"}}; - } - elsif(my $Covered = cover_stdcxx_typedef($ParamAttr{"Name"})) - { - return $Covered; - } - else - { - return $ParamAttr{"Name"}; - } - } - else - { - return $ParamAttr{"Name"}; - } - } -} - -sub cover_stdcxx_typedef($) -{ - my $TypeName = $_[0]; - my $TypeName_Covered = $TypeName; - while($TypeName=~s/>[ ]*(const|volatile|restrict| |\*|\&)\Z/>/g){}; - if(my $Cover = $StdCxxTypedef{$Version}{$TypeName}) - { - $TypeName = esc_l($TypeName); - $TypeName_Covered=~s/$TypeName/$Cover /g; - } - return correctName($TypeName_Covered); -} - -sub getNodeType($) -{ - return $LibInfo{$Version}{$_[0]}{"info_type"}; -} - -sub getNodeIntCst($) -{ - my $CstId = $_[0]; - my $CstTypeId = getTreeAttr($CstId, "type"); - if($EnumMembName_Id{$Version}{$CstId}) - { - return $EnumMembName_Id{$Version}{$CstId}; - } - elsif($LibInfo{$Version}{$_[0]}{"info"} =~ /low[ ]*:[ ]*([^ ]+) /) - { - if($1 eq "0") - { - if(getNodeType($CstTypeId) eq "boolean_type") - { - return "false"; - } - else - { - return "0"; - } - } - elsif($1 eq "1") - { - if(getNodeType($CstTypeId) eq "boolean_type") - { - return "true"; - } - else - { - return "1"; - } - } - else - { - return $1; - } - } - else - { - return ""; - } -} - -sub getNodeStrCst($) -{ - if($LibInfo{$Version}{$_[0]}{"info"} =~ /low[ ]*:[ ]*(.+)[ ]+lngt/) - { - return $1; - } - else - { - return ""; - } -} - -sub esc_l($) -{ - my $String = $_[0]; - $String=~s/([()*])/\\$1/g; - return $String; -} - -sub getFuncPtrAttr($$$) -{ - my ($FuncTypeId, $TypeDeclId, $TypeId) = @_; - my $FuncInfo = $LibInfo{$Version}{$FuncTypeId}{"info"}; - my $FuncInfo_Type = $LibInfo{$Version}{$FuncTypeId}{"info_type"}; - my $FuncPtrCorrectName = ""; - my %TypeAttr = ("Size"=>$POINTER_SIZE, "Type"=>"FuncPtr", "TDid"=>$TypeDeclId, "Tid"=>$TypeId); - my @ParamTypeName; - if($FuncInfo =~ /retn[ ]*:[ ]*\@([0-9]+) /) - { - my $ReturnTypeId = $1; - my %ReturnAttr = getTypeAttr(getTypeDeclId($ReturnTypeId), $ReturnTypeId); - $FuncPtrCorrectName .= $ReturnAttr{"Name"}; - $TypeAttr{"Return"} = $ReturnTypeId; - } - if($FuncInfo =~ /prms[ ]*:[ ]*@([0-9]+) /) - { - my $ParamTypeInfoId = $1; - my $Position = 0; - while($ParamTypeInfoId) - { - my $ParamTypeInfo = $LibInfo{$Version}{$ParamTypeInfoId}{"info"}; - last if($ParamTypeInfo !~ /valu[ ]*:[ ]*@([0-9]+) /); - my $ParamTypeId = $1; - my %ParamAttr = getTypeAttr(getTypeDeclId($ParamTypeId), $ParamTypeId); - last if($ParamAttr{"Name"} eq "void"); - $TypeAttr{"Memb"}{$Position}{"type"} = $ParamTypeId; - push(@ParamTypeName, $ParamAttr{"Name"}); - last if($ParamTypeInfo !~ /chan[ ]*:[ ]*@([0-9]+) /); - $ParamTypeInfoId = $1; - $Position+=1; - } - } - if($FuncInfo_Type eq "function_type") - { - $FuncPtrCorrectName .= " (*) (".join(", ", @ParamTypeName).")"; - } - elsif($FuncInfo_Type eq "method_type") - { - if($FuncInfo =~ /clas[ ]*:[ ]*@([0-9]+) /) - { - my $ClassId = $1; - my $ClassName = $TypeDescr{$Version}{getTypeDeclId($ClassId)}{$ClassId}{"Name"}; - if($ClassName) - { - $FuncPtrCorrectName .= " ($ClassName\:\:*) (".join(", ", @ParamTypeName).")"; - } - else - { - $FuncPtrCorrectName .= " (*) (".join(", ", @ParamTypeName).")"; - } - } - else - { - $FuncPtrCorrectName .= " (*) (".join(", ", @ParamTypeName).")"; - } - } - $TypeAttr{"Name"} = correctName($FuncPtrCorrectName); - return %TypeAttr; -} - -sub getTypeName($) -{ - my $Info = $LibInfo{$Version}{$_[0]}{"info"}; - if($Info =~ /name[ ]*:[ ]*@([0-9]+) /) - { - return getNameByInfo($1); - } - else - { - if($LibInfo{$Version}{$_[0]}{"info_type"} eq "integer_type") - { - if($LibInfo{$Version}{$_[0]}{"info"} =~ /unsigned/) - { - return "unsigned int"; - } - else - { - return "int"; - } - } - else - { - return ""; - } - } -} - -sub selectBaseType($$) -{ - my ($TypeDeclId, $TypeId) = @_; - my $TypeInfo = $LibInfo{$Version}{$TypeId}{"info"}; - my $BaseTypeDeclId; - my $Type_Type = getTypeType($TypeDeclId, $TypeId); - #qualifications - if(($LibInfo{$Version}{$TypeId}{"info"} =~ /qual[ ]*:[ ]*c /) and ($LibInfo{$Version}{$TypeId}{"info"} =~ /unql[ ]*:[ ]*\@([0-9]+) /)) - { - return ($1, getTypeDeclId($1), "const"); - } - elsif(($LibInfo{$Version}{$TypeId}{"info"} =~ /qual[ ]*:[ ]*r /) and ($LibInfo{$Version}{$TypeId}{"info"} =~ /unql[ ]*:[ ]*\@([0-9]+) /)) - { - return ($1, getTypeDeclId($1), "restrict"); - } - elsif(($LibInfo{$Version}{$TypeId}{"info"} =~ /qual[ ]*:[ ]*v /) and ($LibInfo{$Version}{$TypeId}{"info"} =~ /unql[ ]*:[ ]*\@([0-9]+) /)) - { - return ($1, getTypeDeclId($1), "volatile"); - } - elsif((not ($LibInfo{$Version}{$TypeId}{"info"} =~ /qual[ ]*:/)) and ($LibInfo{$Version}{$TypeId}{"info"} =~ /unql[ ]*:[ ]*\@([0-9]+) /)) - {#typedefs - return ($1, getTypeDeclId($1), ""); - } - elsif($LibInfo{$Version}{$TypeId}{"info_type"} eq "reference_type") - { - if($TypeInfo =~ /refd[ ]*:[ ]*@([0-9]+) /) - { - return ($1, getTypeDeclId($1), "&"); - } - else - { - return (0, 0, ""); - } - } - elsif($LibInfo{$Version}{$TypeId}{"info_type"} eq "array_type") - { - if($TypeInfo =~ /elts[ ]*:[ ]*@([0-9]+) /) - { - return ($1, getTypeDeclId($1), ""); - } - else - { - return (0, 0, ""); - } - } - elsif($LibInfo{$Version}{$TypeId}{"info_type"} eq "pointer_type") - { - if($TypeInfo =~ /ptd[ ]*:[ ]*@([0-9]+) /) - { - return ($1, getTypeDeclId($1), "*"); - } - else - { - return (0, 0, ""); - } - } - else - { - return (0, 0, ""); - } -} - -sub getFuncDescr_All() -{ - foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}})) - { - if($LibInfo{$Version}{$_}{"info_type"} eq "function_decl") - { - getFuncDescr($_); - } - } -} - -sub getVarDescr_All() -{ - foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}})) - { - if($LibInfo{$Version}{$_}{"info_type"} eq "var_decl") - { - getVarDescr($_); - } - } -} - -sub getVarDescr($) -{ - my $FuncInfoId = $_[0]; - if($LibInfo{$Version}{getNameSpaceId($FuncInfoId)}{"info_type"} eq "function_decl") - { - return; - } - ($FuncDescr{$Version}{$FuncInfoId}{"Header"}, $FuncDescr{$Version}{$FuncInfoId}{"Line"}) = getLocation($FuncInfoId); - if((not $FuncDescr{$Version}{$FuncInfoId}{"Header"}) or ($FuncDescr{$Version}{$FuncInfoId}{"Header"}=~/\|\/)) - { - delete($FuncDescr{$Version}{$FuncInfoId}); - return; - } - $FuncDescr{$Version}{$FuncInfoId}{"ShortName"} = getNameByInfo($FuncInfoId); - $FuncDescr{$Version}{$FuncInfoId}{"MnglName"} = getFuncMnglName($FuncInfoId); - if($FuncDescr{$Version}{$FuncInfoId}{"MnglName"} and $FuncDescr{$Version}{$FuncInfoId}{"MnglName"}!~/\A_Z/) - { - delete($FuncDescr{$Version}{$FuncInfoId}); - return; - } - if(not $FuncDescr{$Version}{$FuncInfoId}{"MnglName"}) - { - $FuncDescr{$Version}{$FuncInfoId}{"Name"} = $FuncDescr{$Version}{$FuncInfoId}{"ShortName"}; - $FuncDescr{$Version}{$FuncInfoId}{"MnglName"} = $FuncDescr{$Version}{$FuncInfoId}{"ShortName"}; - } - if(not is_in_library($FuncDescr{$Version}{$FuncInfoId}{"MnglName"}, $Version) and not $CheckHeadersOnly) - { - delete $FuncDescr{$Version}{$FuncInfoId}; - return; - } - $FuncDescr{$Version}{$FuncInfoId}{"Return"} = getTypeId($FuncInfoId); - delete($FuncDescr{$Version}{$FuncInfoId}{"Return"}) if(not $FuncDescr{$Version}{$FuncInfoId}{"Return"}); - $FuncDescr{$Version}{$FuncInfoId}{"Data"} = 1; - set_Class_And_Namespace($FuncInfoId); - setFuncAccess($FuncInfoId); - if($FuncDescr{$Version}{$FuncInfoId}{"MnglName"} =~ /\A_ZTV/) - { - delete($FuncDescr{$Version}{$FuncInfoId}{"Return"}); - } - if($FuncDescr{$Version}{$FuncInfoId}{"ShortName"} =~ /\A_Z/) - { - delete($FuncDescr{$Version}{$FuncInfoId}{"ShortName"}); - } -} - -sub getTrivialTypeAttr($$) -{ - my ($TypeInfoId, $TypeId) = @_; - my %TypeAttr = (); - return if(getTypeTypeByTypeId($TypeId)!~/Intrinsic|Union|Struct|Enum/); - setTypeAccess($TypeId, \%TypeAttr); - ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId); - if(($TypeAttr{"Header"} eq "") or ($TypeAttr{"Header"} eq "")) - { - delete($TypeAttr{"Header"}); - } - $TypeAttr{"Name"} = getNameByInfo($TypeInfoId); - $TypeAttr{"Name"} = getTypeName($TypeId) if(not $TypeAttr{"Name"}); - my $NameSpaceId = getNameSpaceId($TypeInfoId); - if($NameSpaceId ne $TypeId) - { - $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId); - } - if($TypeAttr{"NameSpace"} and isNotAnon($TypeAttr{"Name"})) - { - $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"}; - } - $TypeAttr{"Name"} = correctName($TypeAttr{"Name"}); - if(isAnon($TypeAttr{"Name"})) - { - $TypeAttr{"Name"} = "anon-"; - $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"}; - } - $TypeAttr{"Size"} = getSize($TypeId)/8; - $TypeAttr{"Type"} = getTypeType($TypeInfoId, $TypeId); - if($TypeAttr{"Type"} eq "Struct" and has_methods($TypeId)) - { - $TypeAttr{"Type"} = "Class"; - } - if(($TypeAttr{"Type"} eq "Struct") or ($TypeAttr{"Type"} eq "Class")) - { - setBaseClasses($TypeInfoId, $TypeId, \%TypeAttr); - } - setTypeMemb($TypeInfoId, $TypeId, \%TypeAttr); - $TypeAttr{"Tid"} = $TypeId; - $TypeAttr{"TDid"} = $TypeInfoId; - $Tid_TDid{$Version}{$TypeId} = $TypeInfoId; - if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) - { - $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId; - } - return %TypeAttr; -} - -sub has_methods($) -{ - my $TypeId = $_[0]; - my $Info = $LibInfo{$Version}{$TypeId}{"info"}; - return ($Info=~/(fncs)[ ]*:[ ]*@([0-9]+) /); -} - -sub setBaseClasses($$$) -{ - my ($TypeInfoId, $TypeId, $TypeAttr) = @_; - my $Info = $LibInfo{$Version}{$TypeId}{"info"}; - if($Info =~ /binf[ ]*:[ ]*@([0-9]+) /) - { - $Info = $LibInfo{$Version}{$1}{"info"}; - while($Info =~ /accs[ ]*:[ ]*([a-z]+) /) - { - last if($Info !~ s/accs[ ]*:[ ]*([a-z]+) //); - my $Access = $1; - last if($Info !~ s/binf[ ]*:[ ]*@([0-9]+) //); - my $BInfoId = $1; - my $ClassId = getBinfClassId($BInfoId); - if($Access eq "pub") - { - $TypeAttr->{"BaseClass"}{$ClassId} = "public"; - } - elsif($Access eq "prot") - { - $TypeAttr->{"BaseClass"}{$ClassId} = "protected"; - } - elsif($Access eq "priv") - { - $TypeAttr->{"BaseClass"}{$ClassId} = "private"; - } - else - { - $TypeAttr->{"BaseClass"}{$ClassId} = "private"; - } - } - } -} - -sub getBinfClassId($) -{ - my $Info = $LibInfo{$Version}{$_[0]}{"info"}; - $Info =~ /type[ ]*:[ ]*@([0-9]+) /; - return $1; -} - -sub get_func_signature($) -{ - my $FuncInfoId = $_[0]; - my $PureSignature = $FuncDescr{$Version}{$FuncInfoId}{"ShortName"}; - my @ParamTypes = (); - foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$FuncDescr{$Version}{$FuncInfoId}{"Param"}})) - {#checking parameters - my $ParamType_Id = $FuncDescr{$Version}{$FuncInfoId}{"Param"}{$ParamPos}{"type"}; - my $ParamType_Name = uncover_typedefs($TypeDescr{$Version}{getTypeDeclId($ParamType_Id)}{$ParamType_Id}{"Name"}); - @ParamTypes = (@ParamTypes, $ParamType_Name); - } - $PureSignature = $PureSignature."(".join(", ", @ParamTypes).")"; - $PureSignature = delete_keywords($PureSignature); - return correctName($PureSignature); -} - -sub delete_keywords($) -{ - my $TypeName = $_[0]; - $TypeName =~ s/(\W|\A)(enum |struct |union |class )/$1/g; - return $TypeName; -} - -sub uncover_typedefs($) -{ - my $TypeName = $_[0]; - return "" if(not $TypeName); - return $Cache{"uncover_typedefs"}{$Version}{$TypeName} if(defined $Cache{"uncover_typedefs"}{$Version}{$TypeName}); - my ($TypeName_New, $TypeName_Pre) = (correctName($TypeName), ""); - while($TypeName_New ne $TypeName_Pre) - { - $TypeName_Pre = $TypeName_New; - my $TypeName_Copy = $TypeName_New; - my %Words = (); - while($TypeName_Copy=~s/(\W|\A)([a-z_][\w:]*)(\W|\Z)//io) - { - my $Word = $2; - next if(not $Word or $Word=~/\A(true|false|const|int|long|void|short|float|unsigned|char|double|class|struct|union|enum)\Z/); - $Words{$Word} = 1; - } - foreach my $Word (keys(%Words)) - { - my $BaseType_Name = $Typedef_BaseName{$Version}{$Word}; - next if($TypeName_New=~/(\W|\A)(struct $Word|union $Word|enum $Word)(\W|\Z)/); - next if(not $BaseType_Name); - if($BaseType_Name=~/\([*]+\)/) - { - $TypeName_New =~ /$Word(.*)\Z/; - my $Type_Suffix = $1; - $TypeName_New = $BaseType_Name; - if($TypeName_New =~ s/\(([*]+)\)/($1 $Type_Suffix)/) - { - $TypeName_New = correctName($TypeName_New); - } - } - else - { - if($TypeName_New =~ s/(\W|\A)$Word(\W|\Z)/$1$BaseType_Name$2/g) - { - $TypeName_New = correctName($TypeName_New); - } - } - } - } - $Cache{"uncover_typedefs"}{$Version}{$TypeName} = $TypeName_New; - return $TypeName_New; -} - -sub isInternal($) -{ - my $FuncInfoId = $_[0]; - my $FuncInfo = $LibInfo{$Version}{$_[0]}{"info"}; - return 0 if($FuncInfo !~ /mngl[ ]*:[ ]*@([0-9]+) /); - my $FuncMnglNameInfoId = $1; - return ($LibInfo{$Version}{$FuncMnglNameInfoId}{"info"} =~ /\*[ ]*INTERNAL[ ]*\*/); -} - -sub set_Class_And_Namespace($) -{ - my $FuncInfoId = $_[0]; - my $FuncInfo = $LibInfo{$Version}{$FuncInfoId}{"info"}; - if($FuncInfo =~ /scpe[ ]*:[ ]*@([0-9]+) /) - { - my $NameSpaceInfoId = $1; - if($LibInfo{$Version}{$NameSpaceInfoId}{"info_type"} eq "namespace_decl") - { - my $NameSpaceInfo = $LibInfo{$Version}{$NameSpaceInfoId}{"info"}; - if($NameSpaceInfo =~ /name[ ]*:[ ]*@([0-9]+) /) - { - my $NameSpaceId = $1; - my $NameSpaceIdentifier = $LibInfo{$Version}{$NameSpaceId}{"info"}; - if($NameSpaceIdentifier =~ /strg[ ]*:[ ]*(.*)[ ]+lngt/) - { - my $NameSpace = $1; - $NameSpace =~ s/[ ]+\Z//g; - $FuncDescr{$Version}{$FuncInfoId}{"NameSpace"} = $NameSpace; - } - } - } - elsif($LibInfo{$Version}{$NameSpaceInfoId}{"info_type"} eq "record_type") - { - $FuncDescr{$Version}{$FuncInfoId}{"Class"} = $NameSpaceInfoId; - } - } -} - -sub getFuncDescr($) -{ - my $FuncInfoId = $_[0]; - return if(isInternal($FuncInfoId)); - ($FuncDescr{$Version}{$FuncInfoId}{"Header"}, $FuncDescr{$Version}{$FuncInfoId}{"Line"}) = getLocation($FuncInfoId); - if(not $FuncDescr{$Version}{$FuncInfoId}{"Header"} or $FuncDescr{$Version}{$FuncInfoId}{"Header"}=~/\|\/) - { - delete($FuncDescr{$Version}{$FuncInfoId}); - return; - } - setFuncAccess($FuncInfoId); - setFuncKind($FuncInfoId); - if($FuncDescr{$Version}{$FuncInfoId}{"PseudoTemplate"}) - { - delete($FuncDescr{$Version}{$FuncInfoId}); - return; - } - $FuncDescr{$Version}{$FuncInfoId}{"Type"} = getFuncType($FuncInfoId); - $FuncDescr{$Version}{$FuncInfoId}{"Return"} = getFuncReturn($FuncInfoId); - delete($FuncDescr{$Version}{$FuncInfoId}{"Return"}) if(not $FuncDescr{$Version}{$FuncInfoId}{"Return"}); - $FuncDescr{$Version}{$FuncInfoId}{"ShortName"} = getFuncShortName(getFuncOrig($FuncInfoId)); - if($FuncDescr{$Version}{$FuncInfoId}{"ShortName"} =~ /\._/) - { - delete($FuncDescr{$Version}{$FuncInfoId}); - return; - } - if(defined $TemplateInstance_Func{$Version}{$FuncInfoId}) - { - my @TmplParams = (); - foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$TemplateInstance_Func{$Version}{$FuncInfoId}})) - { - my $Param = get_TemplateParam($TemplateInstance_Func{$Version}{$FuncInfoId}{$ParamPos}); - if($Param eq "") - { - delete($FuncDescr{$Version}{$FuncInfoId}); - return; - } - push(@TmplParams, $Param); - } - $FuncDescr{$Version}{$FuncInfoId}{"ShortName"} .= "<".join(", ", @TmplParams).">"; - } - setFuncParams($FuncInfoId); - $FuncDescr{$Version}{$FuncInfoId}{"MnglName"} = getFuncMnglName($FuncInfoId); - if($FuncDescr{$Version}{$FuncInfoId}{"MnglName"} and $FuncDescr{$Version}{$FuncInfoId}{"MnglName"}!~/\A_Z/) - { - delete($FuncDescr{$Version}{$FuncInfoId}); - return; - } - - if((is_in_library($FuncDescr{$Version}{$FuncInfoId}{"ShortName"}, $Version) or $CheckHeadersOnly) and not $FuncDescr{$Version}{$FuncInfoId}{"MnglName"} and ($FuncDescr{$Version}{$FuncInfoId}{"Type"} eq "Function")) - { - $FuncDescr{$Version}{$FuncInfoId}{"MnglName"} = $FuncDescr{$Version}{$FuncInfoId}{"ShortName"}; - } - set_Class_And_Namespace($FuncInfoId); - if(not $FuncDescr{$Version}{$FuncInfoId}{"MnglName"} and not $FuncDescr{$Version}{$FuncInfoId}{"Class"}) - {#this section only for c++ functions without class that have not been mangled in the tree - $FuncDescr{$Version}{$FuncInfoId}{"MnglName"} = $mangled_name{get_func_signature($FuncInfoId)}; - } - if(not is_in_library($FuncDescr{$Version}{$FuncInfoId}{"MnglName"}, $Version) and not $CheckHeadersOnly) - {#src only - delete($FuncDescr{$Version}{$FuncInfoId}); - return; - } - if($FuncDescr{$Version}{$FuncInfoId}{"Constructor"} or $FuncDescr{$Version}{$FuncInfoId}{"Destructor"}) - { - delete($FuncDescr{$Version}{$FuncInfoId}{"Return"}); - } - my $FuncBody = getFuncBody($FuncInfoId); - if($FuncBody eq "defined") - { - $FuncDescr{$Version}{$FuncInfoId}{"InLine"} = 1; - } - if($CheckHeadersOnly and $FuncDescr{$Version}{$FuncInfoId}{"InLine"}) - { - delete($FuncDescr{$Version}{$FuncInfoId}); - return; - } - if(($FuncDescr{$Version}{$FuncInfoId}{"Type"} eq "Method") or $FuncDescr{$Version}{$FuncInfoId}{"Constructor"} or $FuncDescr{$Version}{$FuncInfoId}{"Destructor"}) - { - if($FuncDescr{$Version}{$FuncInfoId}{"MnglName"}!~/\A_Z/) - { - delete($FuncDescr{$Version}{$FuncInfoId}); - return; - } - } - if(getFuncSpec($FuncInfoId) eq "Virt") - {#virtual methods - $FuncDescr{$Version}{$FuncInfoId}{"Virt"} = 1; - } - if(getFuncSpec($FuncInfoId) eq "PureVirt") - {#pure virtual methods - $FuncDescr{$Version}{$FuncInfoId}{"PureVirt"} = 1; - } - if($FuncDescr{$Version}{$FuncInfoId}{"MnglName"} =~ /\A_Z/ and $FuncDescr{$Version}{$FuncInfoId}{"Class"}) - { - if($FuncDescr{$Version}{$FuncInfoId}{"Type"} eq "Function") - {#static methods - $FuncDescr{$Version}{$FuncInfoId}{"Static"} = 1; - } - } - if(getFuncLink($FuncInfoId) eq "Static") - { - $FuncDescr{$Version}{$FuncInfoId}{"Static"} = 1; - } - delete($FuncDescr{$Version}{$FuncInfoId}{"Type"}); -} - -sub getFuncBody($) -{ - my $FuncInfo = $LibInfo{$Version}{$_[0]}{"info"}; - if($FuncInfo =~ /body[ ]*:[ ]*undefined(\ |\Z)/i) - { - return "undefined"; - } - elsif($FuncInfo =~ /body[ ]*:[ ]*@([0-9]+)(\ |\Z)/i) - { - return "defined"; - } - else - { - return ""; - } -} - -sub getTypeShortName($) -{ - my $TypeName = $_[0]; - $TypeName =~ s/\<.*\>//g; - $TypeName =~ s/.*\:\://g; - return $TypeName; -} - -sub getBackRef($) -{ - my $TypeInfo = $LibInfo{$Version}{$_[0]}{"info"}; - if($TypeInfo =~ /name[ ]*:[ ]*@([0-9]+) /) - { - return $1; - } - else - { - return ""; - } -} - -sub getTypeId($) -{ - my $TypeInfo = $LibInfo{$Version}{$_[0]}{"info"}; - if($TypeInfo =~ /type[ ]*:[ ]*@([0-9]+) /) - { - return $1; - } - else - { - return ""; - } -} - -sub getFuncId($) -{ - my $FuncInfo = $LibInfo{$Version}{$_[0]}{"info"}; - if($FuncInfo =~ /type[ ]*:[ ]*@([0-9]+) /) - { - return $1; - } - else - { - return ""; - } -} - -sub setTypeMemb($$) -{ - my ($TypeDeclId, $TypeId, $TypeAttr) = @_; - my $TypeInfo = $LibInfo{$Version}{$TypeId}{"info"}; - my $TypeMembInfoId; - my $TypeType = $TypeAttr->{"Type"}; - my $Position = 0; - my $BasePosition = 0; - my $TypeTypeInfoId; - my $StructMembName; - if($TypeType eq "Enum") - { - $TypeMembInfoId = getEnumMembInfoId($TypeId); - while($TypeMembInfoId) - { - $TypeAttr->{"Memb"}{$Position}{"value"} = getEnumMembVal($TypeMembInfoId); - my $MembName = getEnumMembName($TypeMembInfoId); - $TypeAttr->{"Memb"}{$Position}{"name"} = getEnumMembName($TypeMembInfoId); - $EnumMembName_Id{$Version}{getTreeAttr($TypeMembInfoId, "valu")} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName; - $TypeMembInfoId = getNextMembInfoId($TypeMembInfoId); - $Position += 1; - } - } - elsif(($TypeType eq "Struct") or ($TypeType eq "Class") or ($TypeType eq "Union")) - { - $TypeMembInfoId = getStructMembInfoId($TypeId); - while($TypeMembInfoId) - { - if($LibInfo{$Version}{$TypeMembInfoId}{"info_type"} ne "field_decl") - { - $TypeMembInfoId = getNextStructMembInfoId($TypeMembInfoId); - next; - } - $StructMembName = getStructMembName($TypeMembInfoId); - if($StructMembName =~ /_vptr\./) - {#virtual tables - $TypeMembInfoId = getNextStructMembInfoId($TypeMembInfoId); - next; - } - if(not $StructMembName) - {#base classes - #$TypeAttr->{"Base"}{$BasePosition}{"type"} = getStructMembType($TypeMembInfoId); - #$TypeAttr->{"Base"}{$BasePosition}{"access"} = getStructMembAccess($TypeMembInfoId); - $BasePosition += 1; - $TypeMembInfoId = getNextStructMembInfoId($TypeMembInfoId); - next; - } - $TypeAttr->{"Memb"}{$Position}{"type"} = getStructMembType($TypeMembInfoId); - $TypeAttr->{"Memb"}{$Position}{"name"} = $StructMembName; - $TypeAttr->{"Memb"}{$Position}{"access"} = getStructMembAccess($TypeMembInfoId); - $TypeAttr->{"Memb"}{$Position}{"bitfield"} = getStructMembBitFieldSize($TypeMembInfoId); - - $TypeMembInfoId = getNextStructMembInfoId($TypeMembInfoId); - $Position += 1; - } - } -} - -sub setFuncParams($) -{ - my $FuncInfoId = $_[0]; - my $ParamInfoId = getFuncParamInfoId($FuncInfoId); - my $FunctionType = getFuncType($FuncInfoId); - if($FunctionType eq "Method") - { - $ParamInfoId = getNextElem($ParamInfoId); - } - my $Position = 0; - while($ParamInfoId) - { - my $ParamTypeId = getFuncParamType($ParamInfoId); - last if($TypeDescr{$Version}{getTypeDeclId($ParamTypeId)}{$ParamTypeId}{"Name"} eq "void"); - if($TypeDescr{$Version}{getTypeDeclId($ParamTypeId)}{$ParamTypeId}{"Type"} eq "Restrict") - {#delete restrict spec - $ParamTypeId = getRestrictBase($ParamTypeId); - } - $FuncDescr{$Version}{$FuncInfoId}{"Param"}{$Position}{"type"} = $ParamTypeId; - $FuncDescr{$Version}{$FuncInfoId}{"Param"}{$Position}{"name"} = getFuncParamName($ParamInfoId); - if(not $FuncDescr{$Version}{$FuncInfoId}{"Param"}{$Position}{"name"}) - { - $FuncDescr{$Version}{$FuncInfoId}{"Param"}{$Position}{"name"} = "p".($Position+1); - } - $ParamInfoId = getNextElem($ParamInfoId); - $Position += 1; - } - if(detect_nolimit_args($FuncInfoId)) - { - $FuncDescr{$Version}{$FuncInfoId}{"Param"}{$Position}{"type"} = -1; - } -} - -sub detect_nolimit_args($) -{ - my $FuncInfoId = $_[0]; - my $FuncTypeId = getFuncTypeId($FuncInfoId); - my $ParamListElemId = getFuncParamTreeListId($FuncTypeId); - my $HaveVoid = 0; - my $Position = 0; - while($ParamListElemId) - { - my $ParamTypeId = getTreeAttr($ParamListElemId, "valu"); - if($TypeDescr{$Version}{getTypeDeclId($ParamTypeId)}{$ParamTypeId}{"Name"} eq "void") - { - $HaveVoid = 1; - last; - } - $ParamListElemId = getNextElem($ParamListElemId); - $Position += 1; - } - return ($Position>=1 and not $HaveVoid); -} - -sub getFuncParamTreeListId($) -{ - my $FuncTypeId = $_[0]; - if($LibInfo{$Version}{$FuncTypeId}{"info"} =~ /prms[ ]*:[ ]*@([0-9]+) /) - { - return $1; - } - else - { - return ""; - } -} - -sub getTreeAttr($$) -{ - my ($Id, $Attr) = @_; - if($LibInfo{$Version}{$Id}{"info"} =~ /$Attr[ ]*:[ ]*@([0-9]+) /) - { - return $1; - } - else - { - return ""; - } -} - -sub getRestrictBase($) -{ - my $TypeId = $_[0]; - my $TypeDeclId = getTypeDeclId($TypeId); - my $BaseTypeId = $TypeDescr{$Version}{$TypeDeclId}{$TypeId}{"BaseType"}{"Tid"}; - my $BaseTypeDeclId = $TypeDescr{$Version}{$TypeDeclId}{$TypeId}{"BaseType"}{"TDid"}; - return $BaseTypeId; -} - -sub setFuncAccess($) -{ - my $FuncInfoId = $_[0]; - if($LibInfo{$Version}{$FuncInfoId}{"info"} =~ /accs[ ]*:[ ]*([a-zA-Z]+) /) - { - my $Access = $1; - if($Access eq "prot") - { - $FuncDescr{$Version}{$FuncInfoId}{"Protected"} = 1; - } - elsif($Access eq "priv") - { - $FuncDescr{$Version}{$FuncInfoId}{"Private"} = 1; - } - } -} - -sub setTypeAccess($$) -{ - my ($TypeId, $TypeAttr) = @_; - my $TypeInfo = $LibInfo{$Version}{$TypeId}{"info"}; - if($TypeInfo =~ /accs[ ]*:[ ]*([a-zA-Z]+) /) - { - my $Access = $1; - if($Access eq "prot") - { - $TypeAttr->{"Protected"} = 1; - } - elsif($Access eq "priv") - { - $TypeAttr->{"Private"} = 1; - } - } -} - -sub setFuncKind($) -{ - my $FuncInfoId = $_[0]; - if($LibInfo{$Version}{$FuncInfoId}{"info"} =~ /pseudo tmpl/) - { - $FuncDescr{$Version}{$FuncInfoId}{"PseudoTemplate"} = 1; - } - elsif($LibInfo{$Version}{$FuncInfoId}{"info"} =~ /note[ ]*:[ ]*constructor /) - { - $FuncDescr{$Version}{$FuncInfoId}{"Constructor"} = 1; - } - elsif($LibInfo{$Version}{$FuncInfoId}{"info"} =~ /note[ ]*:[ ]*destructor /) - { - $FuncDescr{$Version}{$FuncInfoId}{"Destructor"} = 1; - } -} - -sub getFuncSpec($) -{ - my $FuncInfoId = $_[0]; - my $FuncInfo = $LibInfo{$Version}{$FuncInfoId}{"info"}; - if($FuncInfo =~ m/spec[ ]*:[ ]*pure /) - { - return "PureVirt"; - } - elsif($FuncInfo =~ m/spec[ ]*:[ ]*virt /) - { - return "Virt"; - } - else - { - if($FuncInfo =~ /spec[ ]*:[ ]*([a-zA-Z]+) /) - { - return $1; - } - else - { - return ""; - } - } -} - -sub getFuncClass($) -{ - my $FuncInfoId = $_[0]; - my $FuncInfo = $LibInfo{$Version}{$FuncInfoId}{"info"}; - if($FuncInfo =~ /scpe[ ]*:[ ]*@([0-9]+) /) - { - return $1; - } - else - { - return ""; - } -} - -sub getFuncLink($) -{ - my $FuncInfoId = $_[0]; - my $FuncInfo = $LibInfo{$Version}{$FuncInfoId}{"info"}; - if($FuncInfo =~ /link[ ]*:[ ]*static /) - { - return "Static"; - } - else - { - if($FuncInfo =~ /link[ ]*:[ ]*([a-zA-Z]+) /) - { - return $1; - } - else - { - return ""; - } - } -} - -sub getNextElem($) -{ - my $FuncInfoId = $_[0]; - my $FuncInfo = $LibInfo{$Version}{$FuncInfoId}{"info"}; - if($FuncInfo =~ /chan[ ]*:[ ]*@([0-9]+) /) - { - return $1; - } - else - { - return ""; - } -} - -sub getFuncParamInfoId($) -{ - my $FuncInfoId = $_[0]; - my $FuncInfo = $LibInfo{$Version}{$FuncInfoId}{"info"}; - if($FuncInfo =~ /args[ ]*:[ ]*@([0-9]+) /) - { - return $1; - } - else - { - return ""; - } -} - -sub getFuncParamType($) -{ - my $ParamInfoId = $_[0]; - my $ParamInfo = $LibInfo{$Version}{$ParamInfoId}{"info"}; - if($ParamInfo =~ /type[ ]*:[ ]*@([0-9]+) /) - { - return $1; - } - else - { - return ""; - } -} - -sub getFuncParamName($) -{ - my $ParamInfoId = $_[0]; - my $ParamInfo = $LibInfo{$Version}{$ParamInfoId}{"info"}; - return "" if($ParamInfo !~ /name[ ]*:[ ]*@([0-9]+) /); - my $NameInfoId = $1; - return "" if($LibInfo{$Version}{$NameInfoId}{"info"} !~ /strg[ ]*:[ ]*(.*)[ ]+lngt/); - my $FuncParamName = $1; - $FuncParamName =~ s/[ ]+\Z//g; - return $FuncParamName; -} - -sub getEnumMembInfoId($) -{ - my $TypeInfoId = $_[0]; - my $TypeInfo = $LibInfo{$Version}{$TypeInfoId}{"info"}; - if($TypeInfo =~ /csts[ ]*:[ ]*@([0-9]+) /) - { - return $1; - } - else - { - return ""; - } -} - -sub getStructMembInfoId($) -{ - my $TypeInfoId = $_[0]; - my $TypeInfo = $LibInfo{$Version}{$TypeInfoId}{"info"}; - if($TypeInfo =~ /flds[ ]*:[ ]*@([0-9]+) /) - { - return $1; - } - else - { - return ""; - } -} - -sub getNameSpace($) -{ - my $TypeInfoId = $_[0]; - my $TypeInfo = $LibInfo{$Version}{$TypeInfoId}{"info"}; - return "" if($TypeInfo !~ /scpe[ ]*:[ ]*@([0-9]+) /); - my $NameSpaceInfoId = $1; - if($LibInfo{$Version}{$NameSpaceInfoId}{"info_type"} eq "namespace_decl") - { - my $NameSpaceInfo = $LibInfo{$Version}{$NameSpaceInfoId}{"info"}; - if($NameSpaceInfo =~ /name[ ]*:[ ]*@([0-9]+) /) - { - my $NameSpaceId = $1; - my $NameSpaceIdentifier = $LibInfo{$Version}{$NameSpaceId}{"info"}; - return "" if($NameSpaceIdentifier !~ /strg[ ]*:[ ]*(.*)[ ]+lngt/); - my $NameSpace = $1; - $NameSpace =~ s/[ ]+\Z//g; - my $BaseNameSpace = getNameSpace($NameSpaceInfoId); - $NameSpace = $BaseNameSpace."::".$NameSpace if($BaseNameSpace); - return $NameSpace; - } - else - { - return ""; - } - } - elsif($LibInfo{$Version}{$NameSpaceInfoId}{"info_type"} eq "record_type") - { - my %NameSpaceAttr = getTypeAttr(getTypeDeclId($NameSpaceInfoId), $NameSpaceInfoId); - return $NameSpaceAttr{"Name"}; - } - else - { - return ""; - } -} - -sub getNameSpaceId($) -{ - my $TypeInfoId = $_[0]; - my $TypeInfo = $LibInfo{$Version}{$TypeInfoId}{"info"}; - if($TypeInfo =~ /scpe[ ]*:[ ]*@([0-9]+) /) - { - return $1; - } - else - { - return ""; - } -} - -sub getEnumMembName($) -{ - my $TypeMembInfoId = $_[0]; - return "" if($LibInfo{$Version}{$TypeMembInfoId}{"info"} !~ /purp[ ]*:[ ]*@([0-9]+)/); - my $Purp = $1; - return "" if($LibInfo{$Version}{$Purp}{"info"} !~ /strg[ ]*:[ ]*(.*)[ ]+lngt/); - my $EnumMembName = $1; - $EnumMembName =~ s/[ ]+\Z//g; - return $EnumMembName; -} - -sub getStructMembName($) -{ - my $TypeMembInfoId = $_[0]; - return "" if($LibInfo{$Version}{$TypeMembInfoId}{"info"} !~ /name[ ]*:[ ]*@([0-9]+) /); - my $NameInfoId = $1; - return "" if($LibInfo{$Version}{$NameInfoId}{"info"} !~ /strg[ ]*:[ ]*(.*)[ ]+lngt/); - my $StructMembName = $1; - $StructMembName =~ s/[ ]+\Z//g; - return $StructMembName; -} - -sub getEnumMembVal($) -{ - my $TypeMembInfoId = $_[0]; - return "" if($LibInfo{$Version}{$TypeMembInfoId}{"info"} !~ /valu[ ]*:[ ]*@([0-9]+) /); - my $Valu = $1; - if($LibInfo{$Version}{$Valu}{"info"} =~ /low[ ]*:[ ]*(-?[0-9]+) /) - { - return $1; - } - else - { - return ""; - } -} - -sub getSize($) -{ - my $Info = $LibInfo{$Version}{$_[0]}{"info"}; - if($Info =~ /size[ ]*:[ ]*@([0-9]+) /) - { - my $SizeInfoId = $1; - if($LibInfo{$Version}{$SizeInfoId}{"info"} =~ /low[ ]*:[ ]*(-?[0-9]+) /) - { - return $1; - } - else - { - return ""; - } - } - else - { - return 0; - } -} - -sub getStructMembType($) -{ - my $TypeMembInfoId = $_[0]; - if($LibInfo{$Version}{$TypeMembInfoId}{"info"} =~ /type[ ]*:[ ]*@([0-9]+) /) - { - return $1; - } - else - { - return ""; - } -} - -sub getStructMembBitFieldSize($) -{ - my $TypeMembInfoId = $_[0]; - if($LibInfo{$Version}{$TypeMembInfoId}{"info"} =~ / bitfield /) - { - return getSize($TypeMembInfoId); - } - else - { - return 0; - } -} - -sub getStructMembAccess($) -{ - my $MembInfo = $LibInfo{$Version}{$_[0]}{"info"}; - if($MembInfo =~ /accs[ ]*:[ ]*([a-zA-Z]+) /) - { - my $Access = $1; - if($Access eq "prot") - { - return "protected"; - } - elsif($Access eq "priv") - { - return "private"; - } - else - { - return "public"; - } - } - else - { - return "public"; - } -} - -sub getNextMembInfoId($) -{ - my $TypeMembInfoId = $_[0]; - if($LibInfo{$Version}{$TypeMembInfoId}{"info"} =~ /chan[ ]*:[ ]*@([0-9]+) /) - { - return $1; - } - else - { - return ""; - } -} - -sub getNextStructMembInfoId($) -{ - my $TypeMembInfoId = $_[0]; - if($LibInfo{$Version}{$TypeMembInfoId}{"info"} =~ /chan[ ]*:[ ]*@([0-9]+) /) - { - return $1; - } - else - { - return ""; - } -} - -sub fieldHasName($) -{ - my $TypeMembInfoId = $_[0]; - if($LibInfo{$Version}{$TypeMembInfoId}{"info_type"} eq "field_decl") - { - if($LibInfo{$Version}{$TypeMembInfoId}{"info"} =~ /name[ ]*:[ ]*@([0-9]+) /) - { - return $1; - } - else - { - return ""; - } - } - else - { - return 0; - } -} - -sub getTypeHeader($) -{ - my $TypeInfo = $LibInfo{$Version}{$_[0]}{"info"}; - if($TypeInfo =~ /srcp[ ]*:[ ]*([0-9a-zA-Z\_\-\<\>\.\+]+):([0-9]+) /) - { - return ($1, $2); - } - else - { - return (); - } -} - -sub register_header($$$) -{ - my ($Destination, $Position, $LibVersion) = @_; - return if(not $Destination); - if($Destination=~/\A\// and not -f $Destination) - { - print "\nERROR: specified header \'$Destination\' does not exist\n"; - return; - } - my $Header_Name = get_FileName($Destination); - $Headers{$LibVersion}{$Destination}{"Name"} = $Header_Name; - $Headers{$LibVersion}{$Destination}{"Position"} = $Position; - $Headers{$LibVersion}{$Destination}{"Identity"} = $Destination; - $HeaderName_Destinations{$LibVersion}{$Header_Name}{$Destination} = 1; -} - -sub headerSearch($) -{ - my $LibVersion = $_[0]; - foreach my $Dest (split("\n", $Descriptor{$LibVersion}{"Include_Paths"})) - { - $Dest =~ s/\A\s+|\s+\Z//g; - next if(not $Dest); - if(not -e $Dest) - { - print "ERROR: can't access \'$Dest\'\n"; - } - $Header_Dependency{$LibVersion}{$Dest} = 1; - } - foreach my $Dest (split("\n", $Descriptor{$LibVersion}{"Headers"})) - {#fill %Header_Dependency - if(-d $Dest) - { - foreach my $Dir (cmd_find($Dest,"d","")) - { - chomp($Dir); - $Header_Dependency{$LibVersion}{$Dir} = 1; - } - } - elsif(-f $Dest) - { - $Header_Dependency{$LibVersion}{get_Dir($Dest)} = 1; - } - } - my $Position = 0; - foreach my $Dest (split("\n", $Descriptor{$LibVersion}{"Headers"})) - { - $Dest =~ s/\A\s+|\s+\Z//g; - next if(not $Dest); - if(is_header($Dest, $LibVersion)) - { - register_header($Dest, $Position, $LibVersion); - $Position += 1; - } - elsif(-d $Dest) - { - foreach my $Destination (sort {lc($a) cmp lc($b)} (cmd_find($Dest,"f",""))) - { - chomp($Destination); - next if(not is_header($Destination, $LibVersion)); - register_header($Destination, $Position, $LibVersion); - $Position += 1; - } - } - else - { - print "WARNING: \'$Dest\' was not found in the specified include paths\n"; - register_header($Dest, $Position, $LibVersion); - $Position += 1; - } - } - if(keys(%{$Headers{$LibVersion}})==1) - { - my $Destination = (keys(%{$Headers{$LibVersion}}))[0]; - $Headers{$LibVersion}{$Destination}{"Identity"} = $Headers{$LibVersion}{$Destination}{"Name"}; - } - foreach my $Header_Name (keys(%{$HeaderName_Destinations{$LibVersion}})) - {#set relative paths (for dublicates) - if(keys(%{$HeaderName_Destinations{$LibVersion}{$Header_Name}})>1) - { - my $FirstDest = (keys(%{$HeaderName_Destinations{$LibVersion}{$Header_Name}}))[0]; - my $Prefix = get_Dir($FirstDest); - while($Prefix =~ /\A(.+)\/[^\/]+\Z/) - { - my $NewPrefix = $1; - my $Changes_Number = 0; - my %Identity = (); - foreach my $Dest (keys(%{$HeaderName_Destinations{$LibVersion}{$Header_Name}})) - { - if($Dest =~ /\A$Prefix\/(.*)\Z/) - { - $Identity{$Dest} = $1; - $Changes_Number+=1; - } - } - if($Changes_Number eq keys(%{$HeaderName_Destinations{$LibVersion}{$Header_Name}})) - { - foreach my $Dest (keys(%{$HeaderName_Destinations{$LibVersion}{$Header_Name}})) - { - $Headers{$LibVersion}{$Dest}{"Identity"} = $Identity{$Dest}; - } - last; - } - $Prefix = $NewPrefix; - } - } - } - if(not keys(%{$Headers{$LibVersion}})) - { - print "ERROR: header files were not found\n"; - exit(1); - } -} - -sub get_FileName($) -{ - my $Path = $_[0]; - if($Path =~ /\A(.*\/)([^\/]*)\Z/) - { - return $2; - } - else - { - return $Path; - } -} - -sub get_Dir($) -{ - my $Path = $_[0]; - return "" if($Path =~ m*\A\./*); - if($Path =~ /\A(.*)\/([^\/]*)\Z/) - { - return $1; - } - else - { - return ""; - } -} - -sub esc($) -{ - my $Str = $_[0]; - $Str =~ s/([()\[\]{}$ &'"`;,<>])/\\$1/g; - return $Str; -} - -sub getLocation($) -{ - my $TypeInfo = $LibInfo{$Version}{$_[0]}{"info"}; - if($TypeInfo =~ /srcp[ ]*:[ ]*([0-9a-zA-Z\_\-\<\>\.\+]+):([0-9]+) /) - { - return ($1, $2); - } - else - { - return (); - } -} - -sub getHeader($) -{ - my $TypeInfo = $LibInfo{$Version}{$_[0]}{"info"}; - if($TypeInfo =~ /srcp[ ]*:[ ]*([0-9a-zA-Z\_\-\<\>\.\+]+):([0-9]+) /) - { - return $1; - } - else - { - return ""; - } -} - -sub getLine($) -{ - my $TypeInfo = $LibInfo{$Version}{$_[0]}{"info"}; - if($TypeInfo =~ /srcp[ ]*:[ ]*([0-9a-zA-Z\_\-\<\>\.\+]+):([0-9]+) /) - { - return $2; - } - else - { - return ""; - } -} - -sub getTypeType($$) -{ - my ($TypeDeclId, $TypeId) = @_; - return "Const" if($LibInfo{$Version}{$TypeId}{"info"} =~ /qual[ ]*:[ ]*c / and $LibInfo{$Version}{$TypeId}{"info"} =~ /unql[ ]*:[ ]*\@/); - return "Typedef" if($LibInfo{$Version}{$TypeId}{"info"} =~ /unql[ ]*:/ and $LibInfo{$Version}{$TypeId}{"info"} !~ /qual[ ]*:/); - return "Volatile" if($LibInfo{$Version}{$TypeId}{"info"} =~ /qual[ ]*:[ ]*v / and $LibInfo{$Version}{$TypeId}{"info"} =~ /unql[ ]*:[ ]*\@/); - return "Restrict" if($LibInfo{$Version}{$TypeId}{"info"} =~ /qual[ ]*:[ ]*r / and $LibInfo{$Version}{$TypeId}{"info"} =~ /unql[ ]*:[ ]*\@/); - my $TypeType = getTypeTypeByTypeId($TypeId); - if($TypeType eq "Struct") - { - if($TypeDeclId and $LibInfo{$Version}{$TypeDeclId}{"info_type"} eq "template_decl") - { - return "Template"; - } - else - { - return "Struct"; - } - } - else - { - return $TypeType; - } - -} - -sub getTypeTypeByTypeId($) -{ - my $TypeId = $_[0]; - my $TypeType = $LibInfo{$Version}{$TypeId}{"info_type"}; - if($TypeType =~ /integer_type|real_type|boolean_type|void_type|complex_type/) - { - return "Intrinsic"; - } - elsif(isFuncPtr($TypeId)) - { - return "FuncPtr"; - } - elsif($TypeType eq "pointer_type") - { - return "Pointer"; - } - elsif($TypeType eq "reference_type") - { - return "Ref"; - } - elsif($TypeType eq "union_type") - { - return "Union"; - } - elsif($TypeType eq "enumeral_type") - { - return "Enum"; - } - elsif($TypeType eq "record_type") - { - return "Struct"; - } - elsif($TypeType eq "array_type") - { - return "Array"; - } - elsif($TypeType eq "complex_type") - { - return "Intrinsic"; - } - elsif($TypeType eq "function_type") - { - return "FunctionType"; - } - elsif($TypeType eq "method_type") - { - return "MethodType"; - } - else - { - return "Unknown"; - } -} - -sub getNameByInfo($) -{ - my $TypeInfo = $LibInfo{$Version}{$_[0]}{"info"}; - return "" if($TypeInfo !~ /name[ ]*:[ ]*@([0-9]+) /); - my $TypeNameInfoId = $1; - return "" if($LibInfo{$Version}{$TypeNameInfoId}{"info"} !~ /strg[ ]*:[ ]*(.*)[ ]+lngt/); - my $TypeName = $1; - $TypeName =~ s/[ ]+\Z//g; - return $TypeName; -} - -sub getFuncShortName($) -{ - my $FuncInfo = $LibInfo{$Version}{$_[0]}{"info"}; - if($FuncInfo =~ / operator /) - { - if($FuncInfo =~ /note[ ]*:[ ]*conversion /) - { - return "operator ".get_TypeName($FuncDescr{$Version}{$_[0]}{"Return"}); - } - else - { - return "" if($FuncInfo !~ / operator[ ]+([a-zA-Z]+) /); - return "operator".$Operator_Indication{$1}; - } - } - else - { - return "" if($FuncInfo !~ /name[ ]*:[ ]*@([0-9]+) /); - my $FuncNameInfoId = $1; - return "" if($LibInfo{$Version}{$FuncNameInfoId}{"info"} !~ /strg[ ]*:[ ]*([^ ]*)[ ]+lngt/); - return $1; - } -} - -sub getFuncMnglName($) -{ - my $FuncInfo = $LibInfo{$Version}{$_[0]}{"info"}; - return "" if($FuncInfo !~ /mngl[ ]*:[ ]*@([0-9]+) /); - my $FuncMnglNameInfoId = $1; - return "" if($LibInfo{$Version}{$FuncMnglNameInfoId}{"info"} !~ /strg[ ]*:[ ]*([^ ]*)[ ]+/); - my $FuncMnglName = $1; - $FuncMnglName =~ s/[ ]+\Z//g; - return $FuncMnglName; -} - -sub getFuncReturn($) -{ - my $FuncInfo = $LibInfo{$Version}{$_[0]}{"info"}; - return "" if($FuncInfo !~ /type[ ]*:[ ]*@([0-9]+) /); - my $FuncTypeInfoId = $1; - return "" if($LibInfo{$Version}{$FuncTypeInfoId}{"info"} !~ /retn[ ]*:[ ]*@([0-9]+) /); - my $FuncReturnTypeId = $1; - if($TypeDescr{$Version}{getTypeDeclId($FuncReturnTypeId)}{$FuncReturnTypeId}{"Type"} eq "Restrict") - {#delete restrict spec - $FuncReturnTypeId = getRestrictBase($FuncReturnTypeId); - } - return $FuncReturnTypeId; -} - -sub getFuncOrig($) -{ - my $FuncInfo = $LibInfo{$Version}{$_[0]}{"info"}; - if($FuncInfo =~ /orig[ ]*:[ ]*@([0-9]+) /) - { - return $1; - } - else - { - return $_[0]; - } -} - -sub unmangleArray(@) -{ - if($#_>$MAX_COMMAND_LINE_ARGUMENTS) - { - my @Half = splice(@_, 0, ($#_+1)/2); - return (unmangleArray(@Half), unmangleArray(@_)) - } - else - { - my $UnmangleCommand = "c++filt ".join(" ", @_); - return split("\n", `$UnmangleCommand`); - } -} - -sub get_Signature($$) -{ - my ($Interface, $LibVersion) = @_; - return $Cache{"get_Signature"}{$Interface}{$LibVersion} if($Cache{"get_Signature"}{$Interface}{$LibVersion}); - my ($MnglName, $SymbolVersion) = ($Interface, ""); - if($Interface =~ /\A([^@]+)[\@]+([^@]+)\Z/) - { - ($MnglName, $SymbolVersion) = ($1, $2); - } - if($MnglName =~ /\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZThn|_ZTv0_n)/) - { - $Cache{"get_Signature"}{$Interface}{$LibVersion} = $tr_name{$MnglName}.(($SymbolVersion)?"\@".$SymbolVersion:""); - return $Cache{"get_Signature"}{$Interface}{$LibVersion}; - } - if(not $CompleteSignature{$LibVersion}{$Interface}) - { - if($Interface =~ /\A_Z/) - { - $Cache{"get_Signature"}{$Interface}{$LibVersion} = $tr_name{$MnglName}.(($SymbolVersion)?"\@".$SymbolVersion:""); - return $Cache{"get_Signature"}{$Interface}{$LibVersion}; - } - else - { - $Cache{"get_Signature"}{$Interface}{$LibVersion} = $Interface; - return $Interface; - } - } - my ($Func_Signature, @Param_Types_FromUnmangledName) = (); - my $ShortName = $CompleteSignature{$LibVersion}{$Interface}{"ShortName"}; - if($Interface =~ /\A_Z/) - { - if($CompleteSignature{$LibVersion}{$Interface}{"Class"}) - { - $Func_Signature = get_TypeName($CompleteSignature{$LibVersion}{$Interface}{"Class"}, $LibVersion)."::".(($CompleteSignature{$LibVersion}{$Interface}{"Destructor"})?"~":"").$ShortName; - } - else - { - $Func_Signature = $ShortName; - } - @Param_Types_FromUnmangledName = get_Signature_Parts($tr_name{$MnglName}, 0); - } - else - { - $Func_Signature = $MnglName; - } - my @ParamArray = (); - foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Interface}{"Param"}})) - { - next if($Pos eq ""); - my $ParamTypeId = $CompleteSignature{$LibVersion}{$Interface}{"Param"}{$Pos}{"type"}; - my $ParamTypeName = $TypeDescr{$LibVersion}{$Tid_TDid{$LibVersion}{$ParamTypeId}}{$ParamTypeId}{"Name"}; - $ParamTypeName = $Param_Types_FromUnmangledName[$Pos] if(not $ParamTypeName); - if(my $ParamName = $CompleteSignature{$LibVersion}{$Interface}{"Param"}{$Pos}{"name"}) - { - if($ParamTypeName=~/\([*]+\)/) - { - $ParamTypeName=~s/\(([*]+)\)/\($1$ParamName\)/; - push(@ParamArray, $ParamTypeName); - } - else - { - push(@ParamArray, $ParamTypeName." ".$ParamName); - } - } - else - { - push(@ParamArray, $ParamTypeName); - } - } - if(not $CompleteSignature{$LibVersion}{$Interface}{"Data"}) - { - if($Interface=~/\A_Z/) - { - if($CompleteSignature{$LibVersion}{$Interface}{"Constructor"}) - { - if($Interface=~/C1/) - { - $Func_Signature .= " [in-charge]"; - } - elsif($Interface=~/C2/) - { - $Func_Signature .= " [not-in-charge]"; - } - } - elsif($CompleteSignature{$LibVersion}{$Interface}{"Destructor"}) - { - if($Interface=~/D1/) - { - $Func_Signature .= " [in-charge]"; - } - elsif($Interface=~/D2/) - { - $Func_Signature .= " [not-in-charge]"; - } - elsif($Interface=~/D0/) - { - $Func_Signature .= " [in-charge-deleting]"; - } - } - } - $Func_Signature .= " (".join(", ", @ParamArray).")"; - } - if($Interface=~/\A_ZNK/) - { - $Func_Signature .= " const"; - } - $Func_Signature .= "\@".$SymbolVersion if($SymbolVersion); - $Cache{"get_Signature"}{$Interface}{$LibVersion} = $Func_Signature; - return $Func_Signature; -} - -sub getVarNameByAttr($) -{ - my $FuncInfoId = $_[0]; - my $VarName; - return "" if(not $FuncDescr{$Version}{$FuncInfoId}{"ShortName"}); - if($FuncDescr{$Version}{$FuncInfoId}{"Class"}) - { - $VarName .= $TypeDescr{$Version}{getTypeDeclId($FuncDescr{$Version}{$FuncInfoId}{"Class"})}{$FuncDescr{$Version}{$FuncInfoId}{"Class"}}{"Name"}; - $VarName .= "::"; - } - $VarName .= $FuncDescr{$Version}{$FuncInfoId}{"ShortName"}; - return $VarName; -} - -sub mangleFuncName($) -{ - my $FuncId = $_[0]; -} - -sub getFuncType($) -{ - my $FuncInfo = $LibInfo{$Version}{$_[0]}{"info"}; - return "" if($FuncInfo !~ /type[ ]*:[ ]*@([0-9]+) /); - my $FuncTypeInfoId = $1; - my $FunctionType = $LibInfo{$Version}{$FuncTypeInfoId}{"info_type"}; - if($FunctionType eq "method_type") - { - return "Method"; - } - elsif($FunctionType eq "function_type") - { - return "Function"; - } - else - { - return $FunctionType; - } -} - -sub getFuncTypeId($) -{ - my $FuncInfo = $LibInfo{$Version}{$_[0]}{"info"}; - if($FuncInfo =~ /type[ ]*:[ ]*@([0-9]+)( |\Z)/) - { - return $1; - } - else - { - return 0; - } -} - -sub isNotAnon($) -{ - return (not isAnon($_[0])); -} - -sub isAnon($) -{ - return (($_[0] =~ m/\.\_[0-9]+/) or ($_[0] =~ m/anon-/)); -} - -sub unmangled_Compact($$) -#Removes all non-essential (for C++ language) whitespace from a string. If -#the whitespace is essential it will be replaced with exactly one ' ' -#character. Works correctly only for unmangled names. -#If level > 1 is supplied, can relax its intent to compact the string. -{ - my $result=$_[0]; - my $level = $_[1] || 1; - my $o1 = ($level>1)?' ':''; - #First, we reduce all spaces that we can - my $coms='[-()<>:*&~!|+=%@~"?.,/[^'."']"; - my $coms_nobr='[-()<:*&~!|+=%@~"?.,'."']"; - my $clos='[),;:\]]'; - $result=~s/^\s+//gm; - $result=~s/\s+$//gm; - $result=~s/((?!\n)\s)+/ /g; - $result=~s/(\w+)\s+($coms+)/$1$o1$2/gm; - #$result=~s/(\w)(\()/$1$o1$2/gm if $o1; - $result=~s/($coms+)\s+(\w+)/$1$o1$2/gm; - $result=~s/(\()\s+(\w)/$1$2/gm if $o1; - $result=~s/(\w)\s+($clos)/$1$2/gm; - $result=~s/($coms+)\s+($coms+)/$1 $2/gm; - $result=~s/($coms_nobr+)\s+($coms+)/$1$o1$2/gm; - $result=~s/($coms+)\s+($coms_nobr+)/$1$o1$2/gm; - #don't forget about >> and <:. In unmangled names global-scope modifier - #is not used, so <: will always be a digraph and requires no special treatment. - #We also try to remove other parts that are better to be removed here than in other places - #double-cv - $result=~s/\bconst\s+const\b/const/gm; - $result=~s/\bvolatile\s+volatile\b/volatile/gm; - $result=~s/\bconst\s+volatile\b\s+const\b/const volatile/gm; - $result=~s/\bvolatile\s+const\b\s+volatile\b/const volatile/gm; - #Place cv in proper order - $result=~s/\bvolatile\s+const\b/const volatile/gm; - return $result; -} - -sub unmangled_PostProcess($) -{ - my $result = $_[0]; - #s/\bunsigned int\b/unsigned/g; - $result =~ s/\bshort unsigned int\b/unsigned short/g; - $result =~ s/\bshort int\b/short/g; - $result =~ s/\blong long unsigned int\b/unsigned long long/g; - $result =~ s/\blong unsigned int\b/unsigned long/g; - $result =~ s/\blong long int\b/long long/g; - $result =~ s/\blong int\b/long/g; - $result =~ s/\)const\b/\) const/g; - $result =~ s/\blong long unsigned\b/unsigned long long/g; - $result =~ s/\blong unsigned\b/unsigned long/g; - return $result; -} - -# From libtodb2/libtodb.pm -# Trim string spaces. -sub trim($) -{ - my $string = shift; - $string =~ s/^\s+//; - $string =~ s/\s+$//; - return $string; -} - -sub correctName($) -{#type name correction - my $CorrectName = $_[0]; - $CorrectName = unmangled_Compact($CorrectName, 1); - $CorrectName = unmangled_PostProcess($CorrectName); - return $CorrectName; -} - -sub getDump_AllInOne() -{ - return if(not keys(%Headers)); - `mkdir -p temp && rm -f temp/*`; - my $Header_Depend = ""; - foreach my $Dep (sort {length($a) <=> length($b)} keys(%{$Header_Dependency{$Version}})) - { - $Header_Depend .= " -I".esc($Dep); - } - my $Lib_VersionName = esc($TargetLibraryName)."_v".$Version; - open(LIB_HEADER, ">temp/$TargetLibraryName"."_v$Version.h"); - foreach my $Preamble_Header (sort {int($Include_Preamble{$Version}{$a}{"Position"})<=>int($Include_Preamble{$Version}{$b}{"Position"})} keys(%{$Include_Preamble{$Version}})) - { - print LIB_HEADER "#include <$Preamble_Header>\n"; - } - foreach my $Destination (sort {int($Headers{$Version}{$a}{"Position"})<=>int($Headers{$Version}{$b}{"Position"})} keys(%{$Headers{$Version}})) - { - my $HName = get_FileName($Destination); - next if($Include_Preamble{$Version}{$Destination} or ($Include_Preamble{$Version}{$HName} and $HeaderName_Destinations{$Version}{$HName} and keys(%{$HeaderName_Destinations{$Version}{$HName}})==1)); - print LIB_HEADER "#include <$Destination>\n"; - } - close(LIB_HEADER); - system("g++ >".esc($ERR_PATH{$Version})." 2>&1 -fdump-translation-unit temp/$Lib_VersionName.h $CompilerOptions{$Version} $Header_Depend"); - if($?) - { - print "WARNING: some errors have occured while compiling header(s), fix it first!\nyou can see compilation errors in the file \'$ERR_PATH{$Version}\'\n"; - } - $ConstantsSrc{$Version} = cmd_preprocessor("temp/$Lib_VersionName.h", $CompilerOptions{$Version}." ".$Header_Depend, "define\\ \\|undef\\ \\|#[ ]\\+[0-9]\\+ \".*\""); - system("mkdir", "-p", "header_compile_errors/$TargetLibraryName/temp/"); - system("cp", "-f", "temp/$TargetLibraryName"."_v$Version.h", "header_compile_errors/$TargetLibraryName/temp/"); - return (split("\n", `find . -maxdepth 1 -name "$Lib_VersionName\.h*\.tu"`))[0]; -} - -sub getDump_Separately($) -{ - `mkdir -p temp`; - `rm -f temp/*`; - my $Destination = $_[0]; - my $Header_Depend = ""; - foreach my $Dep (sort {length($a) <=> length($b)} keys(%{$Header_Dependency{$Version}})) - { - $Header_Depend .= " -I".esc($Dep); - } - my $Lib_VersionName = esc($TargetLibraryName)."_v".$Version; - open(LIB_HEADER, ">temp/$TargetLibraryName"."_v$Version.h"); - foreach my $Preamble_Header (sort {int($Include_Preamble{$Version}{$a}{"Position"})<=>int($Include_Preamble{$Version}{$b}{"Position"})} keys(%{$Include_Preamble{$Version}})) - { - print LIB_HEADER "#include <$Preamble_Header>\n"; - } - my $Destination_HName = get_FileName($Destination); - if(not ( $Include_Preamble{$Version}{$Destination} or ($Include_Preamble{$Version}{$Destination_HName} and $HeaderName_Destinations{$Version}{$Destination_HName} and keys(%{$HeaderName_Destinations{$Version}{$Destination_HName}})==1) )) - { - print LIB_HEADER "#include <$Destination>\n"; - } - close(LIB_HEADER); - system("g++ >>".esc($ERR_PATH{$Version})." 2>&1 -fdump-translation-unit temp/$Lib_VersionName.h $CompilerOptions{$Version} $Header_Depend"); - if($?) - { - $HeaderCompileError{get_FileName($Destination)} = 1; - } - $ConstantsSrc{$Version} .= cmd_preprocessor("temp/$Lib_VersionName.h", $CompilerOptions{$Version}." ".$Header_Depend, "define\\ \\|undef\\ \\|#[ ]\\+[0-9]\\+ \".*\""); - return (split("\n", `find . -maxdepth 1 -name "$Lib_VersionName\.h*\.tu"`))[0]; -} - -sub cmd_file($) -{ - my $Path = $_[0]; - return "" if(not $Path or not -e $Path); - my $Cmd = "file ".esc($Path); - my $Cmd_Out = `$Cmd`; - return $Cmd_Out; -} - -sub cmd_preprocessor($$$) -{ - my ($Path, $AddOpt, $Grep) = @_; - return "" if(not $Path or not -f $Path); - my $Cmd = "g++ -dD -E -x c++-header ".esc($Path)." 2>/dev/null $AddOpt"; - if($Grep) - { - $Cmd .= " | grep \"$Grep\""; - } - my $Cmd_Out = `$Cmd`; - return $Cmd_Out; -} - -sub cmd_cat($$) -{ - my ($Path, $Grep) = @_; - return "" if(not $Path or not -e $Path); - my $Cmd = "cat ".esc($Path); - if($Grep) - { - $Cmd .= " | grep \"$Grep\""; - } - my $Cmd_Out = `$Cmd`; - return $Cmd_Out; -} - -sub cmd_find($$$) -{ - my ($Path, $Type, $Name) = @_; - return () if(not $Path or not -e $Path); - my $Cmd = "find ".esc($Path); - if($Type) - { - $Cmd .= " -type $Type"; - } - if($Name) - { - $Cmd .= " -name \"$Name\""; - } - return split("\n", `$Cmd`); -} - -sub cmd_tar($) -{ - my $Path = $_[0]; - return "" if(not $Path or not -e $Path); - my $Cmd = "tar -xvzf ".esc($Path); - my $Cmd_Out = `$Cmd`; - return $Cmd_Out; -} - -sub is_header($$) -{ - my ($Destination, $LibVersion) = @_; - return 0 if(-d $Destination); - return 1 if($Destination =~ /\.(h|hh|hhh|hpp|tcc)\Z/i); - return 0 if($Destination =~ /\.\w+\Z/i);#cpp|c|gch|tu|fs|pas - if($Destination =~ /\A\//) - { - return (cmd_file($Destination) =~ /:[ ]*ASCII C[\+]* program text/); - } - else - { - foreach my $Prefix (keys(%{$Header_Dependency{$LibVersion}})) - { - my $Path = $Prefix."/".$Destination; - if(-f $Path) - { - if(cmd_file($Path) =~ /:[ ]*ASCII C[\+]* program text/) - { - return 1; - } - } - } - return 0; - } -} - -sub parseHeaders_AllInOne($) -{ - $Version = $_[0]; - print "checking header(s) ".$Descriptor{$Version}{"Version"}." ...\n"; - system("mkdir", "-p", "header_compile_errors/".$TargetLibraryName); - system("rm", "-fr", $ERR_PATH{$Version}); - my $DumpPath = getDump_AllInOne(); - if(not $DumpPath) - { - print "\nERROR: can't create gcc syntax tree for header(s)\nyou can see compilation errors in the file '$ERR_PATH{$Version}'\n"; - exit(1); - } - getInfo($DumpPath); - parse_constants(); - system("rm", "-fr", "temp"); -} - -sub parseHeader($) -{ - my $Destination = $_[0]; - my $DumpPath = getDump_Separately($Destination); - if(not $DumpPath) - { - print "ERROR: can't create gcc syntax tree for header\nyou can see compilation errors in the file '$ERR_PATH{$Version}'\n"; - exit(1); - } - getInfo($DumpPath); - parse_constants(); - system("rm", "-fr", "temp"); -} - -sub is_in_library($$) -{ - my ($MnglName, $LibVersion) = @_; - return ($Interface_Library{$LibVersion}{$MnglName} or ($SymVer{$LibVersion}{$MnglName} and $Interface_Library{$LibVersion}{$SymVer{$LibVersion}{$MnglName}})); -} - -sub prepareInterfaces($) -{ - my $LibVersion = $_[0]; - my (@MnglNames, @UnMnglNames) = (); - if($CheckHeadersOnly) - { - foreach my $FuncInfoId (sort keys(%{$FuncDescr{$LibVersion}})) - { - if($FuncDescr{$LibVersion}{$FuncInfoId}{"MnglName"} =~ /\A_Z/) - { - push(@MnglNames, $FuncDescr{$LibVersion}{$FuncInfoId}{"MnglName"}); - } - } - if($#MnglNames > -1) - { - @UnMnglNames = reverse(unmangleArray(@MnglNames)); - foreach my $FuncInfoId (sort keys(%{$FuncDescr{$LibVersion}})) - { - if($FuncDescr{$LibVersion}{$FuncInfoId}{"MnglName"} =~ /\A_Z/) - { - my $UnmangledName = pop(@UnMnglNames); - $tr_name{$FuncDescr{$LibVersion}{$FuncInfoId}{"MnglName"}} = $UnmangledName; - } - } - } - } - my (%NotMangled_Int, %Mangled_Int) = (); - foreach my $FuncInfoId (keys(%{$FuncDescr{$LibVersion}})) - { - my $MnglName = $FuncDescr{$LibVersion}{$FuncInfoId}{"MnglName"}; - if($MnglName=~/\A_Z/) - { - $Mangled_Int{$FuncInfoId} = $MnglName; - } - else - { - $NotMangled_Int{$FuncInfoId} = $MnglName; - } - next if(not $MnglName or not is_in_library($MnglName, $LibVersion) and not $CheckHeadersOnly); - next if($MnglName =~ /\A_Z/ and $tr_name{$MnglName} =~ /\.\_[0-9]/); - next if(not $FuncDescr{$LibVersion}{$FuncInfoId}{"Header"}); - %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$FuncDescr{$LibVersion}{$FuncInfoId}}; - #interface and its symlink have same signatures - if($SymVer{$LibVersion}{$MnglName}) - { - %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$FuncDescr{$LibVersion}{$FuncInfoId}}; - } - delete($FuncDescr{$LibVersion}{$FuncInfoId}); - } - if(keys(%Mangled_Int)) - { - foreach my $Interface_Id (keys(%NotMangled_Int)) - { - delete($CompleteSignature{$LibVersion}{$NotMangled_Int{$Interface_Id}}); - } - } -} - -my %UsedType; -sub cleanData($) -{ - my $LibVersion = $_[0]; - foreach my $FuncInfoId (keys(%{$FuncDescr{$LibVersion}})) - { - my $MnglName = $FuncDescr{$LibVersion}{$FuncInfoId}{"MnglName"}; - if(not $MnglName or not is_in_library($MnglName, $LibVersion) and not $CheckHeadersOnly) - { - delete($FuncDescr{$LibVersion}{$FuncInfoId}); - next; - } - if(defined $InterfacesListPath and not $InterfacesList{$MnglName}) - { - delete($FuncDescr{$LibVersion}{$FuncInfoId}); - next; - } - if(defined $AppPath and not $InterfacesList_App{$MnglName}) - { - delete($FuncDescr{$LibVersion}{$FuncInfoId}); - next; - } - my %FuncInfo = %{$FuncDescr{$LibVersion}{$FuncInfoId}}; - detect_TypeUsing($Tid_TDid{$LibVersion}{$FuncInfo{"Return"}}, $FuncInfo{"Return"}, $LibVersion); - detect_TypeUsing($Tid_TDid{$LibVersion}{$FuncInfo{"Class"}}, $FuncInfo{"Class"}, $LibVersion); - foreach my $Param_Pos (keys(%{$FuncInfo{"Param"}})) - { - my $Param_TypeId = $FuncInfo{"Param"}{$Param_Pos}{"type"}; - detect_TypeUsing($Tid_TDid{$LibVersion}{$Param_TypeId}, $Param_TypeId, $LibVersion); - } - } - foreach my $TDid (keys(%{$TypeDescr{$LibVersion}})) - { - foreach my $Tid (keys(%{$TypeDescr{$LibVersion}{$TDid}})) - { - if(not $UsedType{$LibVersion}{$TDid}{$Tid}) - { - delete($TypeDescr{$LibVersion}{$TDid}{$Tid}); - if(not keys(%{$TypeDescr{$LibVersion}{$TDid}})) - { - delete($TypeDescr{$LibVersion}{$TDid}); - } - delete($Tid_TDid{$LibVersion}{$Tid}) if($Tid_TDid{$LibVersion}{$Tid} eq $TDid); - } - } - } -} - -sub detect_TypeUsing($$$) -{ - my ($TypeDeclId, $TypeId, $LibVersion) = @_; - return if($UsedType{$LibVersion}{$TypeDeclId}{$TypeId}); - my %Type = get_Type($TypeDeclId, $TypeId, $LibVersion); - if($Type{"Type"} =~ /Struct|Union|Class|FuncPtr|Enum/) - { - $UsedType{$LibVersion}{$TypeDeclId}{$TypeId} = 1; - foreach my $Memb_Pos (keys(%{$Type{"Memb"}})) - { - my $Member_TypeId = $Type{"Memb"}{$Memb_Pos}{"type"}; - detect_TypeUsing($Tid_TDid{$LibVersion}{$Member_TypeId}, $Member_TypeId, $LibVersion); - } - if($Type{"Type"} eq "FuncPtr") - { - my $ReturnType = $Type{"Return"}; - detect_TypeUsing($Tid_TDid{$LibVersion}{$ReturnType}, $ReturnType, $LibVersion); - } - } - elsif($Type{"Type"} =~ /Const|Pointer|Ref|Volatile|Restrict|Array|/) - { - $UsedType{$LibVersion}{$TypeDeclId}{$TypeId} = 1; - detect_TypeUsing($Type{"BaseType"}{"TDid"}, $Type{"BaseType"}{"Tid"}, $LibVersion); - } - elsif($Type{"Type"} eq "Intrinsic") - { - $UsedType{$LibVersion}{$TypeDeclId}{$TypeId} = 1; - } - else - { - delete($TypeDescr{$LibVersion}{$TypeDeclId}{$TypeId}); - if(not keys(%{$TypeDescr{$LibVersion}{$TypeDeclId}})) - { - delete($TypeDescr{$LibVersion}{$TypeDeclId}); - } - delete($Tid_TDid{$LibVersion}{$TypeId}) if($Tid_TDid{$LibVersion}{$TypeId} eq $TypeDeclId); - } -} - -sub initializeClassVirtFunc($) -{ - my $LibVersion = $_[0]; - foreach my $Interface (keys(%{$CompleteSignature{$LibVersion}})) - { - if($CompleteSignature{$LibVersion}{$Interface}{"Virt"}) - { - my $ClassName = $TypeDescr{$LibVersion}{$Tid_TDid{$LibVersion}{$CompleteSignature{$LibVersion}{$Interface}{"Class"}}}{$CompleteSignature{$LibVersion}{$Interface}{"Class"}}{"Name"}; - $ClassVirtFunc{$LibVersion}{$ClassName}{$Interface} = 1; - $ClassIdVirtFunc{$LibVersion}{$CompleteSignature{$LibVersion}{$Interface}{"Class"}}{$Interface} = 1; - $ClassId{$LibVersion}{$ClassName} = $CompleteSignature{$LibVersion}{$Interface}{"Class"}; - } - } -} - -sub checkVirtFuncRedefinitions($) -{ - my $LibVersion = $_[0]; - foreach my $Class_Name (keys(%{$ClassVirtFunc{$LibVersion}})) - { - $CheckedTypes{$Class_Name} = 1; - foreach my $VirtFuncName (keys(%{$ClassVirtFunc{$LibVersion}{$Class_Name}})) - { - $CompleteSignature{$LibVersion}{$VirtFuncName}{"VirtualRedefine"} = find_virtual_method_in_base_classes($VirtFuncName, $ClassId{$LibVersion}{$Class_Name}, $LibVersion); - } - } -} - -sub setVirtFuncPositions($) -{ - my $LibVersion = $_[0]; - foreach my $Class_Name (keys(%{$ClassVirtFunc{$LibVersion}})) - { - $CheckedTypes{$Class_Name} = 1; - my $Position = 0; - foreach my $VirtFuncName (sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} keys(%{$ClassVirtFunc{$LibVersion}{$Class_Name}})) - { - if($ClassVirtFunc{1}{$Class_Name}{$VirtFuncName} and $ClassVirtFunc{2}{$Class_Name}{$VirtFuncName} and not $CompleteSignature{1}{$VirtFuncName}{"VirtualRedefine"} and not $CompleteSignature{2}{$VirtFuncName}{"VirtualRedefine"}) - { - $CompleteSignature{$LibVersion}{$VirtFuncName}{"Position"} = $Position; - $Position += 1; - } - } - } -} - -sub check_VirtualTable($$) -{ - my ($TargetFunction, $LibVersion) = @_; - my $Class_Id = $CompleteSignature{$LibVersion}{$TargetFunction}{"Class"}; - my $Class_DId = $Tid_TDid{$LibVersion}{$Class_Id}; - my %Class_Type = get_Type($Class_DId, $Class_Id, $LibVersion); - $CheckedTypes{$Class_Type{"Name"}} = 1; - foreach my $VirtFuncName (keys(%{$ClassVirtFunc{2}{$Class_Type{"Name"}}})) - {#Added - if($ClassId{1}{$Class_Type{"Name"}} and not $ClassVirtFunc{1}{$Class_Type{"Name"}}{$VirtFuncName} and $AddedInt{$VirtFuncName}) - { - if($CompleteSignature{2}{$VirtFuncName}{"VirtualRedefine"}) - { - if($TargetFunction eq $VirtFuncName) - { - my $BaseClass_Id = $CompleteSignature{2}{$CompleteSignature{2}{$VirtFuncName}{"VirtualRedefine"}}{"Class"}; - my %BaseClass_Type = get_Type($Tid_TDid{2}{$BaseClass_Id}, $BaseClass_Id, 2); - my $BaseClass_Name = $BaseClass_Type{"Name"}; - %{$CompatProblems{$TargetFunction}{"Virtual_Function_Redefinition"}{$tr_name{$CompleteSignature{2}{$VirtFuncName}{"VirtualRedefine"}}}}=( - "Type_Name"=>$Class_Type{"Name"}, - "Type_Type"=>$Class_Type{"Type"}, - "Header"=>$CompleteSignature{2}{$TargetFunction}{"Header"}, - "Line"=>$CompleteSignature{2}{$TargetFunction}{"Line"}, - "Target"=>$tr_name{$CompleteSignature{2}{$VirtFuncName}{"VirtualRedefine"}}, - "Signature"=>$tr_name{$TargetFunction}, - "Old_Value"=>$tr_name{$CompleteSignature{2}{$VirtFuncName}{"VirtualRedefine"}}, - "New_Value"=>$tr_name{$TargetFunction}, - "Old_SoName"=>$Interface_Library{1}{$TargetFunction}, - "New_SoName"=>$Interface_Library{2}{$TargetFunction} ); - } - } - elsif($TargetFunction ne $VirtFuncName) - { - %{$CompatProblems{$TargetFunction}{"Added_Virtual_Function"}{$tr_name{$VirtFuncName}}}=( - "Type_Name"=>$Class_Type{"Name"}, - "Type_Type"=>$Class_Type{"Type"}, - "Header"=>$Class_Type{"Header"}, - "Line"=>$Class_Type{"Line"}, - "Target"=>$tr_name{$VirtFuncName}, - "Signature"=>$tr_name{$TargetFunction}, - "Old_SoName"=>$Interface_Library{1}{$TargetFunction}, - "New_SoName"=>$Interface_Library{2}{$TargetFunction} ); - } - } - } - foreach my $VirtFuncName (keys(%{$ClassVirtFunc{1}{$Class_Type{"Name"}}})) - {#Withdrawn - if($ClassId{2}{$Class_Type{"Name"}} and not $ClassVirtFunc{2}{$Class_Type{"Name"}}{$VirtFuncName} and $WithdrawnInt{$VirtFuncName}) - { - if($CompleteSignature{1}{$VirtFuncName}{"VirtualRedefine"}) - { - if($TargetFunction eq $VirtFuncName) - { - my $BaseClass_Id = $CompleteSignature{1}{$CompleteSignature{1}{$VirtFuncName}{"VirtualRedefine"}}{"Class"}; - my $BaseClass_Name = $TypeDescr{1}{$Tid_TDid{1}{$BaseClass_Id}}{$BaseClass_Id}{"Name"}; - %{$CompatProblems{$TargetFunction}{"Virtual_Function_Redefinition_B"}{$tr_name{$CompleteSignature{1}{$VirtFuncName}{"VirtualRedefine"}}}}=( - "Type_Name"=>$Class_Type{"Name"}, - "Type_Type"=>$Class_Type{"Type"}, - "Header"=>$CompleteSignature{2}{$TargetFunction}{"Header"}, - "Line"=>$CompleteSignature{2}{$TargetFunction}{"Line"}, - "Target"=>$tr_name{$CompleteSignature{1}{$VirtFuncName}{"VirtualRedefine"}}, - "Signature"=>$tr_name{$TargetFunction}, - "Old_Value"=>$tr_name{$TargetFunction}, - "New_Value"=>$tr_name{$CompleteSignature{1}{$VirtFuncName}{"VirtualRedefine"}}, - "Old_SoName"=>$Interface_Library{1}{$TargetFunction}, - "New_SoName"=>$Interface_Library{2}{$TargetFunction} ); - } - } - else - { - %{$CompatProblems{$TargetFunction}{"Withdrawn_Virtual_Function"}{$tr_name{$VirtFuncName}}}=( - "Type_Name"=>$Class_Type{"Name"}, - "Type_Type"=>$Class_Type{"Type"}, - "Header"=>$Class_Type{"Header"}, - "Line"=>$Class_Type{"Line"}, - "Target"=>$tr_name{$VirtFuncName}, - "Signature"=>$tr_name{$TargetFunction}, - "Old_SoName"=>$Interface_Library{1}{$TargetFunction}, - "New_SoName"=>$Interface_Library{2}{$TargetFunction} ); - } - } - } -} - -sub find_virtual_method_in_base_classes($$$) -{ - my ($VirtFuncName, $Checked_ClassId, $LibVersion) = @_; - foreach my $BaseClass_Id (keys(%{$TypeDescr{$LibVersion}{$Tid_TDid{$LibVersion}{$Checked_ClassId}}{$Checked_ClassId}{"BaseClass"}})) - { - my $VirtMethodInClass = find_virtual_method_in_class($VirtFuncName, $BaseClass_Id, $LibVersion); - if($VirtMethodInClass) - { - return $VirtMethodInClass; - } - my $VirtMethodInBaseClasses = find_virtual_method_in_base_classes($VirtFuncName, $BaseClass_Id, $LibVersion); - if($VirtMethodInBaseClasses) - { - return $VirtMethodInBaseClasses; - } - } - return ""; -} - -sub find_virtual_method_in_class($$$) -{ - my ($VirtFuncName, $Checked_ClassId, $LibVersion) = @_; - my $Suffix = getFuncSuffix($VirtFuncName, $LibVersion); - foreach my $Checked_VirtFuncName (keys(%{$ClassIdVirtFunc{$LibVersion}{$Checked_ClassId}})) - { - if($Suffix eq getFuncSuffix($Checked_VirtFuncName, $LibVersion) - and ((not $CompleteSignature{$LibVersion}{$VirtFuncName}{"Constructor"} and not $CompleteSignature{$LibVersion}{$VirtFuncName}{"Destructor"} and $CompleteSignature{$LibVersion}{$VirtFuncName}{"ShortName"} eq $CompleteSignature{$LibVersion}{$Checked_VirtFuncName}{"ShortName"}) or ($CompleteSignature{$LibVersion}{$VirtFuncName}{"Constructor"} or $CompleteSignature{$LibVersion}{$VirtFuncName}{"Destructor"}))) - { - return $Checked_VirtFuncName; - } - } - return ""; -} - -sub getFuncSuffix($$) -{ - my ($FuncName, $LibVersion) = @_; - my $ClassId = $CompleteSignature{$LibVersion}{$FuncName}{"Class"}; - my $ClassName = $TypeDescr{$LibVersion}{$Tid_TDid{$LibVersion}{$ClassId}}{$ClassId}{"Name"}; - my $ShortName = $CompleteSignature{$LibVersion}{$FuncName}{"ShortName"}; - my $Suffix = $tr_name{$FuncName}; - $Suffix =~ s/\A$ClassName\:\:[~]*$ShortName[ ]*//g; - return $Suffix; -} - -sub isRecurType($$$$) -{ - foreach (@RecurTypes) - { - if($_->{"Tid1"} eq $_[0] - and $_->{"TDid1"} eq $_[1] - and $_->{"Tid2"} eq $_[2] - and $_->{"TDid2"} eq $_[3]) - { - return 1; - } - } - return 0; -} - -sub find_MemberPair_Pos_byName($$) -{ - my ($Member_Name, $Pair_Type) = @_; - foreach my $MemberPair_Pos (sort keys(%{$Pair_Type->{"Memb"}})) - { - if($Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"} eq $Member_Name) - { - return $MemberPair_Pos; - } - } - return "lost"; -} - -sub getBitfieldSum($$) -{ - my ($Member_Pos, $Pair_Type) = @_; - my $BitfieldSum = 0; - while($Member_Pos>-1) - { - return $BitfieldSum if(not $Pair_Type->{"Memb"}{$Member_Pos}{"bitfield"}); - $BitfieldSum += $Pair_Type->{"Memb"}{$Member_Pos}{"bitfield"}; - $Member_Pos -= 1; - } - return $BitfieldSum; -} - -sub find_MemberPair_Pos_byVal($$) -{ - my ($Member_Value, $Pair_Type) = @_; - foreach my $MemberPair_Pos (sort keys(%{$Pair_Type->{"Memb"}})) - { - if($Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) - { - return $MemberPair_Pos; - } - } - return "lost"; -} - -my %Priority_Value=( -"High"=>3, -"Medium"=>2, -"Low"=>1 -); - -sub max_priority($$) -{ - my ($Priority1, $Priority2) = @_; - if(cmp_priority($Priority1, $Priority2)) - { - return $Priority1; - } - else - { - return $Priority2; - } -} - -sub cmp_priority($$) -{ - my ($Priority1, $Priority2) = @_; - return ($Priority_Value{$Priority1}>$Priority_Value{$Priority2}); -} - -sub set_Problems_Priority() -{ - foreach my $InterfaceName (sort keys(%CompatProblems)) - { - foreach my $Kind (sort keys(%{$CompatProblems{$InterfaceName}})) - { - foreach my $Location (sort keys(%{$CompatProblems{$InterfaceName}{$Kind}})) - { - my $IsInTypeInternals = $CompatProblems{$InterfaceName}{$Kind}{$Location}{"IsInTypeInternals"}; - my $InitialType_Type = $CompatProblems{$InterfaceName}{$Kind}{$Location}{"InitialType_Type"}; - if($Kind eq "Function_Become_Static") - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "High"; - } - elsif($Kind eq "Function_Become_NonStatic") - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "High"; - } - elsif($Kind eq "Parameter_Type_And_Size") - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "High"; - } - elsif($Kind eq "Parameter_Type") - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low"; - } - elsif($Kind eq "Withdrawn_Parameter") - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Medium"; - } - elsif($Kind eq "Added_Parameter") - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Medium"; - } - elsif($Kind eq "Parameter_BaseType_And_Size") - { - if($InitialType_Type eq "Pointer") - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low"; - } - else - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "High"; - } - } - elsif($Kind eq "Parameter_BaseType") - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low"; - } - elsif($Kind eq "Parameter_PointerLevel") - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "High"; - } - elsif($Kind eq "Return_Type_And_Size") - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Medium"; - } - elsif($Kind eq "Return_Type") - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low"; - } - elsif($Kind eq "Return_BaseType_And_Size") - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Medium"; - } - elsif($Kind eq "Return_BaseType") - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low"; - } - elsif($Kind eq "Return_PointerLevel") - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low"; - } - if($Kind eq "Added_Virtual_Function") - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "High"; - } - elsif($Kind eq "Withdrawn_Virtual_Function") - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "High"; - } - elsif($Kind eq "Virtual_Function_Position") - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "High"; - } - elsif($Kind eq "Virtual_Function_Redefinition") - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low"; - } - elsif($Kind eq "Virtual_Function_Redefinition_B") - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low"; - } - elsif($Kind eq "Size") - { - if(($InitialType_Type eq "Pointer") or ($InitialType_Type eq "Array")) - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low"; - } - else - { - if($IsInTypeInternals) - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Medium"; - } - else - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "High"; - } - } - } - elsif($Kind eq "BaseType") - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low"; - } - elsif($Kind eq "Added_Member_And_Size") - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low"; - } - elsif($Kind eq "Added_Middle_Member_And_Size") - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Medium"; - } - elsif($Kind eq "Withdrawn_Member_And_Size") - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Medium"; - } - elsif($Kind eq "Withdrawn_Member") - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low"; - } - elsif($Kind eq "Withdrawn_Middle_Member_And_Size") - { - if($IsInTypeInternals) - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Medium"; - } - else - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "High"; - } - } - elsif($Kind eq "Withdrawn_Middle_Member") - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Medium"; - } - elsif($Kind eq "Member_Rename") - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low"; - } - elsif($Kind eq "Enum_Member_Value") - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Medium"; - } - elsif($Kind eq "Enum_Member_Name") - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low"; - } - elsif($Kind eq "Member_Type_And_Size") - { - if(($InitialType_Type eq "Pointer") or ($InitialType_Type eq "Array")) - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low"; - } - else - { - if($IsInTypeInternals) - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low"; - } - else - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "High"; - } - } - } - elsif($Kind eq "Member_Type") - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low"; - } - elsif($Kind eq "Member_BaseType_And_Size") - { - if(($InitialType_Type eq "Pointer") or ($InitialType_Type eq "Array")) - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low"; - } - else - { - if($IsInTypeInternals) - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low"; - } - else - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "High"; - } - } - } - elsif($Kind eq "Member_BaseType") - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low"; - } - elsif($Kind eq "Member_PointerLevel") - { - if(($InitialType_Type eq "Pointer") or ($InitialType_Type eq "Array")) - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low"; - } - else - { - if($IsInTypeInternals) - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low"; - } - else - { - $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Medium"; - } - } - } - } - } - } -} - -sub pushType($$$$) -{ - my %TypeDescriptor=( - "Tid1" => $_[0], - "TDid1" => $_[1], - "Tid2" => $_[2], - "TDid2" => $_[3] ); - push(@RecurTypes, \%TypeDescriptor); -} - -sub mergeTypes($$$$) -{ - my ($Type1_Id, $Type1_DId, $Type2_Id, $Type2_DId) = @_; - my (%Sub_SubProblems, %SubProblems) = (); - if((not $Type1_Id and not $Type1_DId) or (not $Type2_Id and not $Type2_DId)) - {#Not Empty Inputs Only - return (); - } - if($Cache{"mergeTypes"}{$Type1_Id}{$Type1_DId}{$Type2_Id}{$Type2_DId}) - {#Already Merged - return %{$Cache{"mergeTypes"}{$Type1_Id}{$Type1_DId}{$Type2_Id}{$Type2_DId}}; - } - my %Type1 = get_Type($Type1_DId, $Type1_Id, 1); - my %Type2 = get_Type($Type2_DId, $Type2_Id, 2); - my %Type1_Pure = get_PureType($Type1_DId, $Type1_Id, 1); - my %Type2_Pure = get_PureType($Type2_DId, $Type2_Id, 2); - return () if(not $Type1_Pure{"Size"} or not $Type2_Pure{"Size"}); - if(isRecurType($Type1_Pure{"Tid"}, $Type1_Pure{"TDid"}, $Type2_Pure{"Tid"}, $Type2_Pure{"TDid"})) - {#Recursive Declarations - return (); - } - return if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"}); - return if($OpaqueTypes{1}{$Type1_Pure{"Name"}} or $OpaqueTypes{2}{$Type1_Pure{"Name"}} or $OpaqueTypes{1}{$Type1{"Name"}} or $OpaqueTypes{2}{$Type1{"Name"}}); - - my %Typedef_1 = goToFirst($Type1{"TDid"}, $Type1{"Tid"}, 1, "Typedef"); - my %Typedef_2 = goToFirst($Type2{"TDid"}, $Type2{"Tid"}, 2, "Typedef"); - if($Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef" and $Typedef_1{"Name"} eq $Typedef_2{"Name"}) - { - my %Base_1 = get_OneStep_BaseType($Typedef_1{"TDid"}, $Typedef_1{"Tid"}, 1); - my %Base_2 = get_OneStep_BaseType($Typedef_2{"TDid"}, $Typedef_2{"Tid"}, 2); - if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/ - and ($Base_1{"Name"} ne $Base_2{"Name"})) - { - %{$SubProblems{"BaseType"}{$Typedef_1{"Name"}}}=( - "Type_Name"=>$Typedef_1{"Name"}, - "Type_Type"=>"Typedef", - "Header"=>$Typedef_2{"Header"}, - "Line"=>$Typedef_2{"Line"}, - "Old_Value"=>$Base_1{"Name"}, - "New_Value"=>$Base_2{"Name"} ); - } - } - - if(($Type1_Pure{"Name"} ne $Type2_Pure{"Name"}) and ($Type1_Pure{"Type"} ne "Pointer") and $Type1_Pure{"Name"}!~/anon\-/) - {#Different types - return (); - } - - pushType($Type1_Pure{"Tid"}, $Type1_Pure{"TDid"}, $Type2_Pure{"Tid"}, $Type2_Pure{"TDid"}); - if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}) and ($Type1_Pure{"Type"} =~ /Struct|Class|Union/)) - {#Check Size - if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) - { - %{$SubProblems{"Size"}{$Type1_Pure{"Name"}}}=( - "Type_Name"=>$Type1_Pure{"Name"}, - "Type_Type"=>$Type1_Pure{"Type"}, - "Header"=>$Type2_Pure{"Header"}, - "Line"=>$Type2_Pure{"Line"}, - "Old_Value"=>$Type1_Pure{"Size"}, - "New_Value"=>$Type2_Pure{"Size"} ); - } - } - if($Type1_Pure{"Name"} and $Type2_Pure{"Name"} and ($Type1_Pure{"Name"} ne $Type2_Pure{"Name"}) and ($Type1_Pure{"Name"} !~ /\Avoid[ ]*\*/) and ($Type2_Pure{"Name"} =~ /\Avoid[ ]*\*/)) - {#Check "void *" - pop(@RecurTypes); - return (); - } - if($Type1_Pure{"BaseType"}{"Tid"} and $Type2_Pure{"BaseType"}{"Tid"}) - {#Check Base Types - %Sub_SubProblems = &mergeTypes($Type1_Pure{"BaseType"}{"Tid"}, $Type1_Pure{"BaseType"}{"TDid"}, $Type2_Pure{"BaseType"}{"Tid"}, $Type2_Pure{"BaseType"}{"TDid"}); - foreach my $Sub_SubProblemType (keys(%Sub_SubProblems)) - { - foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems{$Sub_SubProblemType}})) - { - %{$SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}} = %{$Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}}; - $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}{"InitialType_Type"} = $Type1_Pure{"Type"}; - } - } - } - foreach my $Member_Pos (sort keys(%{$Type1_Pure{"Memb"}})) - {#Check Members - next if($Type1_Pure{"Memb"}{$Member_Pos}{"access"} eq "private"); - my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"}; - next if(not $Member_Name); - my $Member_Location = $Member_Name; - my $MemberPair_Pos = find_MemberPair_Pos_byName($Member_Name, \%Type2_Pure); - if(($MemberPair_Pos eq "lost") and (($Type2_Pure{"Type"} eq "Struct") or ($Type2_Pure{"Type"} eq "Class"))) - {#Withdrawn_Member - if($Member_Pos > keys(%{$Type2_Pure{"Memb"}}) - 1) - { - if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) - { - %{$SubProblems{"Withdrawn_Member_And_Size"}{$Member_Name}}=( - "Target"=>$Member_Name, - "Type_Name"=>$Type1_Pure{"Name"}, - "Type_Type"=>$Type1_Pure{"Type"}, - "Header"=>$Type2_Pure{"Header"}, - "Line"=>$Type2_Pure{"Line"}, - "Old_Size"=>$Type1_Pure{"Size"}, - "New_Size"=>$Type2_Pure{"Size"} ); - } - else - { - %{$SubProblems{"Withdrawn_Member"}{$Member_Name}}=( - "Target"=>$Member_Name, - "Type_Name"=>$Type1_Pure{"Name"}, - "Type_Type"=>$Type1_Pure{"Type"}, - "Header"=>$Type2_Pure{"Header"}, - "Line"=>$Type2_Pure{"Line"} ); - } - next; - } - elsif($Member_Pos < keys(%{$Type1_Pure{"Memb"}}) - 1) - { - my $MemberType_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"}; - my %MemberType_Pure = get_PureType($Tid_TDid{1}{$MemberType_Id}, $MemberType_Id, 1); - my $MemberStraightPairType_Id = $Type2_Pure{"Memb"}{$Member_Pos}{"type"}; - my %MemberStraightPairType_Pure = get_PureType($Tid_TDid{2}{$MemberStraightPairType_Id}, $MemberStraightPairType_Id, 2); - - if(($MemberType_Pure{"Size"} eq $MemberStraightPairType_Pure{"Size"}) and find_MemberPair_Pos_byName($Type2_Pure{"Memb"}{$Member_Pos}{"name"}, \%Type1_Pure) eq "lost") - { - %{$SubProblems{"Member_Rename"}{$Member_Name}}=( - "Target"=>$Member_Name, - "Type_Name"=>$Type1_Pure{"Name"}, - "Type_Type"=>$Type1_Pure{"Type"}, - "Header"=>$Type2_Pure{"Header"}, - "Line"=>$Type2_Pure{"Line"}, - "Old_Value"=>$Type1_Pure{"Memb"}{$Member_Pos}{"name"}, - "New_Value"=>$Type2_Pure{"Memb"}{$Member_Pos}{"name"} ); - $MemberPair_Pos = $Member_Pos; - } - else - { - if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) - { - my $BitfieldSum = getBitfieldSum($Member_Pos-1, \%Type1_Pure)%($POINTER_SIZE*8); - if($BitfieldSum and $BitfieldSum-$Type2_Pure{"Memb"}{$Member_Pos}{"bitfield"}>=0) - { - %{$SubProblems{"Withdrawn_Middle_Member"}{$Member_Name}}=( - "Target"=>$Member_Name, - "Type_Name"=>$Type1_Pure{"Name"}, - "Type_Type"=>$Type1_Pure{"Type"}, - "Header"=>$Type2_Pure{"Header"}, - "Line"=>$Type2_Pure{"Line"} ); - next; - } - } - %{$SubProblems{"Withdrawn_Middle_Member_And_Size"}{$Member_Name}}=( - "Target"=>$Member_Name, - "Type_Name"=>$Type1_Pure{"Name"}, - "Type_Type"=>$Type1_Pure{"Type"}, - "Header"=>$Type2_Pure{"Header"}, - "Line"=>$Type2_Pure{"Line"} ); - next; - } - } - } - if($Type1_Pure{"Type"} eq "Enum") - { - my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"}; - next if(not $Member_Value1); - my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"}; - if($MemberPair_Pos eq "lost") - { - $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure); - if($MemberPair_Pos ne "lost") - { - %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=( - "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"}, - "Type_Name"=>$Type1_Pure{"Name"}, - "Type_Type"=>"Enum", - "Header"=>$Type2_Pure{"Header"}, - "Line"=>$Type2_Pure{"Line"}, - "Old_Value"=>$Type1_Pure{"Memb"}{$Member_Pos}{"name"}, - "New_Value"=>$Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"} ); - } - } - else - { - if($Member_Value1 ne "" and $Member_Value2 ne "") - { - if($Member_Value1 ne $Member_Value2) - { - %{$SubProblems{"Enum_Member_Value"}{$Member_Name}}=( - "Target"=>$Member_Name, - "Type_Name"=>$Type1_Pure{"Name"}, - "Type_Type"=>"Enum", - "Header"=>$Type2_Pure{"Header"}, - "Line"=>$Type2_Pure{"Line"}, - "Old_Value"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"}, - "New_Value"=>$Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"} ); - } - } - } - next; - } - my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"}; - my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"}; - %Sub_SubProblems = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Member"); - foreach my $Sub_SubProblemType (keys(%Sub_SubProblems)) - { - %{$SubProblems{$Sub_SubProblemType}{$Member_Name}}=( - "Target"=>$Member_Name, - "Member_Position"=>$Member_Pos, - "Type_Name"=>$Type1_Pure{"Name"}, - "Type_Type"=>$Type1_Pure{"Type"}, - "Header"=>$Type2_Pure{"Header"}, - "Line"=>$Type2_Pure{"Line"}); - @{$SubProblems{$Sub_SubProblemType}{$Member_Name}}{keys(%{$Sub_SubProblems{$Sub_SubProblemType}})} = values %{$Sub_SubProblems{$Sub_SubProblemType}}; - } - if($MemberType1_Id and $MemberType2_Id) - {#checking member type change (replace) - %Sub_SubProblems = &mergeTypes($MemberType1_Id, $Tid_TDid{1}{$MemberType1_Id}, $MemberType2_Id, $Tid_TDid{2}{$MemberType2_Id}); - foreach my $Sub_SubProblemType (keys(%Sub_SubProblems)) - { - foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems{$Sub_SubProblemType}})) - { - my $NewLocation = ($Sub_SubLocation)?$Member_Location."->".$Sub_SubLocation:$Member_Location; - %{$SubProblems{$Sub_SubProblemType}{$NewLocation}}=( - "IsInTypeInternals"=>"Yes"); - @{$SubProblems{$Sub_SubProblemType}{$NewLocation}}{keys(%{$Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}})} = values %{$Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}}; - if($Sub_SubLocation !~ /\-\>/) - { - $SubProblems{$Sub_SubProblemType}{$NewLocation}{"Member_Type_Name"} = get_TypeName($MemberType1_Id, 1); - $SubProblems{$Sub_SubProblemType}{$NewLocation}{"Start_Type_Name"} = get_TypeName($MemberType1_Id, 1); - } - } - } - } - } - if(($Type2_Pure{"Type"} eq "Struct") or ($Type2_Pure{"Type"} eq "Class")) - { - foreach my $Member_Pos (sort keys(%{$Type2_Pure{"Memb"}})) - {#checking added members - next if(not $Type2_Pure{"Memb"}{$Member_Pos}{"name"}); - my $MemberPair_Pos = find_MemberPair_Pos_byName($Type2_Pure{"Memb"}{$Member_Pos}{"name"}, \%Type1_Pure); - if($MemberPair_Pos eq "lost") - {#Added_Member - if($Member_Pos > keys(%{$Type1_Pure{"Memb"}}) - 1) - { - if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) - { - if($Type2_Pure{"Memb"}{$Member_Pos}{"bitfield"}) - { - my $BitfieldSum = getBitfieldSum($Member_Pos-1, \%Type2_Pure)%($POINTER_SIZE*8); - next if($BitfieldSum and $BitfieldSum<=$POINTER_SIZE*8-$Type2_Pure{"Memb"}{$Member_Pos}{"bitfield"}); - } - %{$SubProblems{"Added_Member_And_Size"}{$Type2_Pure{"Memb"}{$Member_Pos}{"name"}}}=( - "Target"=>$Type2_Pure{"Memb"}{$Member_Pos}{"name"}, - "Type_Name"=>$Type1_Pure{"Name"}, - "Type_Type"=>$Type1_Pure{"Type"}, - "Header"=>$Type2_Pure{"Header"}, - "Line"=>$Type2_Pure{"Line"} ); - } - } - else - { - my $MemberType_Id = $Type2_Pure{"Memb"}{$Member_Pos}{"type"}; - my $MemberType_DId = $Tid_TDid{2}{$MemberType_Id}; - my %MemberType_Pure = get_PureType($MemberType_DId, $MemberType_Id, 2); - - my $MemberStraightPairType_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"}; - my %MemberStraightPairType_Pure = get_PureType($Tid_TDid{1}{$MemberStraightPairType_Id}, $MemberStraightPairType_Id, 1); - - if(($MemberType_Pure{"Size"} eq $MemberStraightPairType_Pure{"Size"}) and find_MemberPair_Pos_byName($Type1_Pure{"Memb"}{$Member_Pos}{"name"}, \%Type2_Pure) eq "lost") - { - next if($Type1_Pure{"Memb"}{$Member_Pos}{"access"} eq "private"); - %{$SubProblems{"Member_Rename"}{$Type2_Pure{"Memb"}{$Member_Pos}{"name"}}}=( - "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"name"}, - "Type_Name"=>$Type1_Pure{"Name"}, - "Type_Type"=>$Type1_Pure{"Type"}, - "Header"=>$Type2_Pure{"Header"}, - "Line"=>$Type2_Pure{"Line"}, - "Old_Value"=>$Type1_Pure{"Memb"}{$Member_Pos}{"name"}, - "New_Value"=>$Type2_Pure{"Memb"}{$Member_Pos}{"name"} ); - } - else - { - if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) - { - if($Type2_Pure{"Memb"}{$Member_Pos}{"bitfield"}) - { - my $BitfieldSum = getBitfieldSum($Member_Pos-1, \%Type2_Pure)%($POINTER_SIZE*8); - next if($BitfieldSum and $BitfieldSum<=$POINTER_SIZE*8-$Type2_Pure{"Memb"}{$Member_Pos}{"bitfield"}); - } - %{$SubProblems{"Added_Middle_Member_And_Size"}{$Type2_Pure{"Memb"}{$Member_Pos}{"name"}}}=( - "Target"=>$Type2_Pure{"Memb"}{$Member_Pos}{"name"}, - "Type_Name"=>$Type1_Pure{"Name"}, - "Type_Type"=>$Type1_Pure{"Type"}, - "Header"=>$Type2_Pure{"Header"}, - "Line"=>$Type2_Pure{"Line"} ); - } - } - } - } - } - } - %{$Cache{"mergeTypes"}{$Type1_Id}{$Type1_DId}{$Type2_Id}{$Type2_DId}} = %SubProblems; - pop(@RecurTypes); - return %SubProblems; -} - -sub get_TypeName($$) -{ - my ($TypeId, $LibVersion) = @_; - return $TypeDescr{$LibVersion}{$Tid_TDid{$LibVersion}{$TypeId}}{$TypeId}{"Name"}; -} - -sub goToFirst($$$$) -{ - my ($TypeDId, $TypeId, $LibVersion, $Type_Type) = @_; - if(defined $Cache{"goToFirst"}{$TypeDId}{$TypeId}{$LibVersion}{$Type_Type}) - { - return %{$Cache{"goToFirst"}{$TypeDId}{$TypeId}{$LibVersion}{$Type_Type}}; - } - return () if(not $TypeDescr{$LibVersion}{$TypeDId}{$TypeId}); - my %Type = %{$TypeDescr{$LibVersion}{$TypeDId}{$TypeId}}; - return () if(not $Type{"Type"}); - if($Type{"Type"} ne $Type_Type) - { - return () if(not $Type{"BaseType"}{"TDid"} and not $Type{"BaseType"}{"Tid"}); - %Type = goToFirst($Type{"BaseType"}{"TDid"}, $Type{"BaseType"}{"Tid"}, $LibVersion, $Type_Type); - } - $Cache{"goToFirst"}{$TypeDId}{$TypeId}{$LibVersion}{$Type_Type} = \%Type; - return %Type; -} - -my %TypeSpecAttributes = ( - "Ref" => 1, - "Const" => 1, - "Volatile" => 1, - "Restrict" => 1, - "Typedef" => 1 -); - -sub get_PureType($$$) -{ - my ($TypeDId, $TypeId, $LibVersion) = @_; - return "" if(not $TypeId); - if(defined $Cache{"get_PureType"}{$TypeDId}{$TypeId}{$LibVersion}) - { - return %{$Cache{"get_PureType"}{$TypeDId}{$TypeId}{$LibVersion}}; - } - return "" if(not $TypeDescr{$LibVersion}{$TypeDId}{$TypeId}); - my %Type = %{$TypeDescr{$LibVersion}{$TypeDId}{$TypeId}}; - if($Type{"Type"} =~ /Struct|Union|Typedef|Class|Enum/) - { - $CheckedTypes{$Type{"Name"}} = 1; - } - return %Type if(not $Type{"BaseType"}{"TDid"} and not $Type{"BaseType"}{"Tid"}); - if($TypeSpecAttributes{$Type{"Type"}}) - { - %Type = get_PureType($Type{"BaseType"}{"TDid"}, $Type{"BaseType"}{"Tid"}, $LibVersion); - } - $Cache{"get_PureType"}{$TypeDId}{$TypeId}{$LibVersion} = \%Type; - return %Type; -} - -sub get_PointerLevel($$$) -{ - my ($TypeDId, $TypeId, $LibVersion) = @_; - return "" if(not $TypeId); - if(defined $Cache{"get_PointerLevel"}{$TypeDId}{$TypeId}{$LibVersion}) - { - return $Cache{"get_PointerLevel"}{$TypeDId}{$TypeId}{$LibVersion}; - } - return "" if(not $TypeDescr{$LibVersion}{$TypeDId}{$TypeId}); - my %Type = %{$TypeDescr{$LibVersion}{$TypeDId}{$TypeId}}; - return 0 if(not $Type{"BaseType"}{"TDid"} and not $Type{"BaseType"}{"Tid"}); - my $PointerLevel = 0; - if($Type{"Type"} eq "Pointer") - { - $PointerLevel += 1; - } - $PointerLevel += get_PointerLevel($Type{"BaseType"}{"TDid"}, $Type{"BaseType"}{"Tid"}, $LibVersion); - $Cache{"get_PointerLevel"}{$TypeDId}{$TypeId}{$LibVersion} = $PointerLevel; - return $PointerLevel; -} - -sub get_BaseType($$$) -{ - my ($TypeDId, $TypeId, $LibVersion) = @_; - return "" if(not $TypeId); - if(defined $Cache{"get_BaseType"}{$TypeDId}{$TypeId}{$LibVersion}) - { - return %{$Cache{"get_BaseType"}{$TypeDId}{$TypeId}{$LibVersion}}; - } - return "" if(not $TypeDescr{$LibVersion}{$TypeDId}{$TypeId}); - my %Type = %{$TypeDescr{$LibVersion}{$TypeDId}{$TypeId}}; - if($Type{"Type"} =~ /Struct|Union|Typedef|Class|Enum/) - { - $CheckedTypes{$Type{"Name"}} = 1; - } - return %Type if(not $Type{"BaseType"}{"TDid"} and not $Type{"BaseType"}{"Tid"}); - %Type = get_BaseType($Type{"BaseType"}{"TDid"}, $Type{"BaseType"}{"Tid"}, $LibVersion); - $Cache{"get_BaseType"}{$TypeDId}{$TypeId}{$LibVersion} = \%Type; - return %Type; -} - -sub get_OneStep_BaseType($$$) -{ - my ($TypeDId, $TypeId, $LibVersion) = @_; - return "" if(not $TypeId); - return "" if(not $TypeDescr{$LibVersion}{$TypeDId}{$TypeId}); - my %Type = %{$TypeDescr{$LibVersion}{$TypeDId}{$TypeId}}; - return %Type if(not $Type{"BaseType"}{"TDid"} and not $Type{"BaseType"}{"Tid"}); - return get_Type($Type{"BaseType"}{"TDid"}, $Type{"BaseType"}{"Tid"}, $LibVersion); -} - -sub get_Type($$$) -{ - my ($TypeDId, $TypeId, $LibVersion) = @_; - return "" if(not $TypeId); - return "" if(not $TypeDescr{$LibVersion}{$TypeDId}{$TypeId}); - return %{$TypeDescr{$LibVersion}{$TypeDId}{$TypeId}}; -} - -sub mergeLibs() -{ - foreach my $Interface (sort keys(%AddedInt)) - {#checking added interfaces - next if($InternalInterfaces{1}{$Interface} or $InternalInterfaces{2}{$Interface}); - next if(defined $InterfacesListPath and not $InterfacesList{$Interface}); - next if(defined $AppPath and not $InterfacesList_App{$Interface}); - next if($FuncAttr{2}{$Interface}{"Private"}); - next if(not $FuncAttr{2}{$Interface}{"Header"}); - %{$CompatProblems{$Interface}{"Added_Interface"}{"SharedLibrary"}}=( - "Header"=>$FuncAttr{2}{$Interface}{"Header"}, - "Line"=>$FuncAttr{2}{$Interface}{"Line"}, - "Signature"=>$FuncAttr{2}{$Interface}{"Signature"}, - "New_SoName"=>$Interface_Library{2}{$Interface} ); - } - foreach my $Interface (sort keys(%WithdrawnInt)) - {#checking withdrawn interfaces - next if($InternalInterfaces{1}{$Interface} or $InternalInterfaces{2}{$Interface}); - next if(defined $InterfacesListPath and not $InterfacesList{$Interface}); - next if(defined $AppPath and not $InterfacesList_App{$Interface}); - next if($FuncAttr{1}{$Interface}{"Private"}); - next if(not $FuncAttr{1}{$Interface}{"Header"}); - %{$CompatProblems{$Interface}{"Withdrawn_Interface"}{"SharedLibrary"}}=( - "Header"=>$FuncAttr{1}{$Interface}{"Header"}, - "Line"=>$FuncAttr{1}{$Interface}{"Line"}, - "Signature"=>$FuncAttr{1}{$Interface}{"Signature"}, - "Old_SoName"=>$Interface_Library{1}{$Interface} ); - } -} - -sub mergeSignatures() -{ - my %SubProblems = (); - - prepareInterfaces(1); - prepareInterfaces(2); - %FuncDescr=(); - - initializeClassVirtFunc(1); - initializeClassVirtFunc(2); - - checkVirtFuncRedefinitions(1); - checkVirtFuncRedefinitions(2); - - setVirtFuncPositions(1); - setVirtFuncPositions(2); - - foreach my $Interface (sort keys(%AddedInt)) - {#collecting the attributes of added interfaces - next if($CheckedInterfaces{$Interface}); - if($CompleteSignature{2}{$Interface}) - { - if($CompleteSignature{2}{$Interface}{"Private"}) - { - $FuncAttr{2}{$Interface}{"Private"} = 1; - } - if($CompleteSignature{2}{$Interface}{"Protected"}) - { - $FuncAttr{2}{$Interface}{"Protected"} = 1; - } - if($CompleteSignature{2}{$Interface}{"Header"}) - { - $FuncAttr{2}{$Interface}{"Header"} = $CompleteSignature{2}{$Interface}{"Header"}; - } - if($CompleteSignature{2}{$Interface}{"Line"}) - { - $FuncAttr{2}{$Interface}{"Line"} = $CompleteSignature{2}{$Interface}{"Line"}; - } - $FuncAttr{2}{$Interface}{"Signature"} = get_Signature($Interface, 2); - foreach my $ParamPos (keys(%{$CompleteSignature{2}{$Interface}{"Param"}})) - { - my $ParamType_Id = $CompleteSignature{2}{$Interface}{"Param"}{$ParamPos}{"type"}; - my $ParamType_DId = $Tid_TDid{2}{$ParamType_Id}; - my %ParamType = get_Type($ParamType_DId, $ParamType_Id, 2); - } - #checking virtual table - check_VirtualTable($Interface, 2); - $CheckedInterfaces{$Interface} = 1; - } - } - foreach my $Interface (sort keys(%WithdrawnInt)) - {#collecting the attributes of withdrawn interfaces - next if($CheckedInterfaces{$Interface}); - if($CompleteSignature{1}{$Interface}) - { - if($CompleteSignature{1}{$Interface}{"Private"}) - { - $FuncAttr{1}{$Interface}{"Private"} = 1; - } - if($CompleteSignature{1}{$Interface}{"Protected"}) - { - $FuncAttr{1}{$Interface}{"Protected"} = 1; - } - if($CompleteSignature{1}{$Interface}{"Header"}) - { - $FuncAttr{1}{$Interface}{"Header"} = $CompleteSignature{1}{$Interface}{"Header"}; - } - if($CompleteSignature{1}{$Interface}{"Line"}) - { - $FuncAttr{1}{$Interface}{"Line"} = $CompleteSignature{1}{$Interface}{"Line"}; - } - $FuncAttr{1}{$Interface}{"Signature"} = get_Signature($Interface, 1); - foreach my $ParamPos (keys(%{$CompleteSignature{1}{$Interface}{"Param"}})) - { - my $ParamType_Id = $CompleteSignature{1}{$Interface}{"Param"}{$ParamPos}{"type"}; - my $ParamType_DId = $Tid_TDid{1}{$ParamType_Id}; - my %ParamType = get_Type($ParamType_DId, $ParamType_Id, 1); - } - #checking virtual table - check_VirtualTable($Interface, 1); - $CheckedInterfaces{$Interface} = 1; - } - } - - foreach my $Interface (sort keys(%{$CompleteSignature{1}})) - {#checking interfaces - if(($Interface !~ /\@/) and ($SymVer{1}{$Interface} =~ /\A(.*)[\@]+/)) - { - next if($1 eq $Interface); - } - my ($MnglName, $SymbolVersion) = ($Interface, ""); - if($Interface =~ /\A([^@]+)[\@]+([^@]+)\Z/) - { - ($MnglName, $SymbolVersion) = ($1, $2); - } - next if($InternalInterfaces{1}{$Interface} or $InternalInterfaces{2}{$Interface}); - next if(defined $InterfacesListPath and not $InterfacesList{$Interface}); - next if(defined $AppPath and not $InterfacesList_App{$Interface}); - next if($CheckedInterfaces{$Interface}); - next if($CompleteSignature{1}{$Interface}{"Private"}); - next if(not $CompleteSignature{1}{$Interface}{"Header"} or not $CompleteSignature{2}{$Interface}{"Header"}); - next if(not $CompleteSignature{1}{$Interface}{"MnglName"} or not $CompleteSignature{2}{$Interface}{"MnglName"}); - next if((not $CompleteSignature{1}{$Interface}{"PureVirt"} and $CompleteSignature{2}{$Interface}{"PureVirt"}) or ($CompleteSignature{1}{$Interface}{"PureVirt"} and not $CompleteSignature{2}{$Interface}{"PureVirt"})); - $CheckedInterfaces{$Interface} = 1; - #checking virtual table - check_VirtualTable($Interface, 1); - #checking attributes - if($CompleteSignature{2}{$Interface}{"Static"} and not $CompleteSignature{1}{$Interface}{"Static"}) - { - %{$CompatProblems{$Interface}{"Function_Become_Static"}{"Attributes"}}=( - "Header"=>$CompleteSignature{1}{$Interface}{"Header"}, - "Line"=>$CompleteSignature{1}{$Interface}{"Line"}, - "Signature"=>get_Signature($Interface, 1), - "Old_SoName"=>$Interface_Library{1}{$Interface}, - "New_SoName"=>$Interface_Library{2}{$Interface} ); - } - elsif(not $CompleteSignature{2}{$Interface}{"Static"} and $CompleteSignature{1}{$Interface}{"Static"}) - { - %{$CompatProblems{$Interface}{"Function_Become_NonStatic"}{"Attributes"}}=( - "Header"=>$CompleteSignature{1}{$Interface}{"Header"}, - "Line"=>$CompleteSignature{1}{$Interface}{"Line"}, - "Signature"=>get_Signature($Interface, 1), - "Old_SoName"=>$Interface_Library{1}{$Interface}, - "New_SoName"=>$Interface_Library{2}{$Interface} ); - } - if($CompleteSignature{1}{$Interface}{"Virt"} and $CompleteSignature{2}{$Interface}{"Virt"}) - { - if($CompleteSignature{1}{$Interface}{"Position"}!=$CompleteSignature{2}{$Interface}{"Position"}) - { - my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"}; - my $Class_DId = $Tid_TDid{1}{$Class_Id}; - my %Class_Type = get_Type($Class_DId, $Class_Id, 1); - %{$CompatProblems{$Interface}{"Virtual_Function_Position"}{$tr_name{$MnglName}}}=( - "Type_Name"=>$Class_Type{"Name"}, - "Type_Type"=>$Class_Type{"Type"}, - "Header"=>$Class_Type{"Header"}, - "Line"=>$Class_Type{"Line"}, - "Old_Value"=>$CompleteSignature{1}{$Interface}{"Position"}, - "New_Value"=>$CompleteSignature{2}{$Interface}{"Position"}, - "Signature"=>get_Signature($Interface, 1), - "Target"=>$tr_name{$MnglName}, - "Old_SoName"=>$Interface_Library{1}{$Interface}, - "New_SoName"=>$Interface_Library{2}{$Interface} ); - } - } - foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$Interface}{"Param"}})) - {#checking added parameters - last if($Interface=~/\A_Z/); - if(not defined $CompleteSignature{1}{$Interface}{"Param"}{$ParamPos}) - {#checking withdrawn parameters - my $ParamType2_Id = $CompleteSignature{2}{$Interface}{"Param"}{$ParamPos}{"type"}; - my $Parameter_Name = $CompleteSignature{2}{$Interface}{"Param"}{$ParamPos}{"name"}; - last if(get_TypeName($ParamType2_Id, 2) eq "..."); - %{$CompatProblems{$Interface}{"Added_Parameter"}{num_to_str($ParamPos+1)." Parameter"}}=( - "Target"=>$Parameter_Name, - "Parameter_Position"=>$ParamPos, - "Signature"=>get_Signature($Interface, 1), - "Header"=>$CompleteSignature{1}{$Interface}{"Header"}, - "Line"=>$CompleteSignature{1}{$Interface}{"Line"}, - "Old_SoName"=>$Interface_Library{1}{$Interface}, - "New_SoName"=>$Interface_Library{2}{$Interface}); - } - } - foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Interface}{"Param"}})) - {#checking parameters - my $ParamType1_Id = $CompleteSignature{1}{$Interface}{"Param"}{$ParamPos}{"type"}; - my $Parameter_Name = $CompleteSignature{1}{$Interface}{"Param"}{$ParamPos}{"name"}; - if(not defined $CompleteSignature{2}{$Interface}{"Param"}{$ParamPos} and get_TypeName($ParamType1_Id, 1) ne "..." and $Interface!~/\A_Z/) - {#checking withdrawn parameters - %{$CompatProblems{$Interface}{"Withdrawn_Parameter"}{num_to_str($ParamPos+1)." Parameter"}}=( - "Target"=>$Parameter_Name, - "Parameter_Position"=>$ParamPos, - "Signature"=>get_Signature($Interface, 1), - "Header"=>$CompleteSignature{1}{$Interface}{"Header"}, - "Line"=>$CompleteSignature{1}{$Interface}{"Line"}, - "Old_SoName"=>$Interface_Library{1}{$Interface}, - "New_SoName"=>$Interface_Library{2}{$Interface}); - next; - } - my $ParamType2_Id = $CompleteSignature{2}{$Interface}{"Param"}{$ParamPos}{"type"}; - next if(not $ParamType1_Id or not $ParamType2_Id); - my $Parameter_Location = ($Parameter_Name)?$Parameter_Name:num_to_str($ParamPos+1)." Parameter"; - - #checking type change(replace) - %SubProblems = detectTypeChange($ParamType1_Id, $ParamType2_Id, "Parameter"); - foreach my $SubProblemType (keys(%SubProblems)) - { - %{$CompatProblems{$Interface}{$SubProblemType}{$Parameter_Location}}=( - "Target"=>$Parameter_Name, - "Parameter_Position"=>$ParamPos, - "Signature"=>get_Signature($Interface, 1), - "Header"=>$CompleteSignature{1}{$Interface}{"Header"}, - "Line"=>$CompleteSignature{1}{$Interface}{"Line"}, - "Old_SoName"=>$Interface_Library{1}{$Interface}, - "New_SoName"=>$Interface_Library{2}{$Interface}); - @{$CompatProblems{$Interface}{$SubProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}}; - } - @RecurTypes = (); - #checking type definition changes - %SubProblems = mergeTypes($ParamType1_Id, $Tid_TDid{1}{$ParamType1_Id}, $ParamType2_Id, $Tid_TDid{2}{$ParamType2_Id}); - foreach my $SubProblemType (keys(%SubProblems)) - { - foreach my $SubLocation (keys(%{$SubProblems{$SubProblemType}})) - { - my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location; - %{$CompatProblems{$Interface}{$SubProblemType}{$NewLocation}}=( - "Signature"=>get_Signature($Interface, 1), - "Header"=>$CompleteSignature{1}{$Interface}{"Header"}, - "Line"=>$CompleteSignature{1}{$Interface}{"Line"}, - "Old_SoName"=>$Interface_Library{1}{$Interface}, - "New_SoName"=>$Interface_Library{2}{$Interface}, - "Parameter_Type_Name"=>get_TypeName($ParamType1_Id, 1), - "Parameter_Position"=>$ParamPos, - "Parameter_Name"=>$Parameter_Name); - @{$CompatProblems{$Interface}{$SubProblemType}{$NewLocation}}{keys(%{$SubProblems{$SubProblemType}{$SubLocation}})} = values %{$SubProblems{$SubProblemType}{$SubLocation}}; - if($SubLocation !~ /\-\>/) - { - $CompatProblems{$Interface}{$SubProblemType}{$NewLocation}{"Start_Type_Name"} = get_TypeName($ParamType1_Id, 1); - } - } - } - } - #checking return type - my $ReturnType1_Id = $CompleteSignature{1}{$Interface}{"Return"}; - my $ReturnType2_Id = $CompleteSignature{2}{$Interface}{"Return"}; - %SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return"); - foreach my $SubProblemType (keys(%SubProblems)) - { - %{$CompatProblems{$Interface}{$SubProblemType}{"RetVal"}}=( - "Signature"=>get_Signature($Interface, 1), - "Header"=>$CompleteSignature{1}{$Interface}{"Header"}, - "Line"=>$CompleteSignature{1}{$Interface}{"Line"}, - "Old_SoName"=>$Interface_Library{1}{$Interface}, - "New_SoName"=>$Interface_Library{2}{$Interface}); - @{$CompatProblems{$Interface}{$SubProblemType}{"RetVal"}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}}; - } - if($ReturnType1_Id and $ReturnType2_Id) - { - @RecurTypes = (); - %SubProblems = mergeTypes($ReturnType1_Id, $Tid_TDid{1}{$ReturnType1_Id}, $ReturnType2_Id, $Tid_TDid{2}{$ReturnType2_Id}); - foreach my $SubProblemType (keys(%SubProblems)) - { - foreach my $SubLocation (keys(%{$SubProblems{$SubProblemType}})) - { - my $NewLocation = ($SubLocation)?"RetVal->".$SubLocation:"RetVal"; - %{$CompatProblems{$Interface}{$SubProblemType}{$NewLocation}}=( - "Signature"=>get_Signature($Interface, 1), - "Header"=>$CompleteSignature{1}{$Interface}{"Header"}, - "Line"=>$CompleteSignature{1}{$Interface}{"Line"}, - "Old_SoName"=>$Interface_Library{1}{$Interface}, - "New_SoName"=>$Interface_Library{2}{$Interface}, - "Return_Type_Name"=>get_TypeName($ReturnType1_Id, 1) ); - @{$CompatProblems{$Interface}{$SubProblemType}{$NewLocation}}{keys(%{$SubProblems{$SubProblemType}{$SubLocation}})} = values %{$SubProblems{$SubProblemType}{$SubLocation}}; - if($SubLocation !~ /\-\>/) - { - $CompatProblems{$Interface}{$SubProblemType}{$NewLocation}{"Start_Type_Name"} = get_TypeName($ReturnType1_Id, 1); - } - } - } - } - - #checking object type - my $ObjectType1_Id = $CompleteSignature{1}{$Interface}{"Class"}; - my $ObjectType2_Id = $CompleteSignature{2}{$Interface}{"Class"}; - if($ObjectType1_Id and $ObjectType2_Id) - { - my $ThisType1_Id = getTypeIdByName(get_TypeName($ObjectType1_Id, 1)."*const", 1); - my $ThisType2_Id = getTypeIdByName(get_TypeName($ObjectType2_Id, 2)."*const", 2); - if($ThisType1_Id and $ThisType2_Id) - { - @RecurTypes = (); - %SubProblems = mergeTypes($ThisType1_Id, $Tid_TDid{1}{$ThisType1_Id}, $ThisType2_Id, $Tid_TDid{2}{$ThisType2_Id}); - foreach my $SubProblemType (keys(%SubProblems)) - { - foreach my $SubLocation (keys(%{$SubProblems{$SubProblemType}})) - { - my $NewLocation = ($SubLocation)?"Obj->".$SubLocation:"Obj"; - %{$CompatProblems{$Interface}{$SubProblemType}{$NewLocation}}=( - "Signature"=>get_Signature($Interface, 1), - "Header"=>$CompleteSignature{1}{$Interface}{"Header"}, - "Line"=>$CompleteSignature{1}{$Interface}{"Line"}, - "Old_SoName"=>$Interface_Library{1}{$Interface}, - "New_SoName"=>$Interface_Library{2}{$Interface}, - "Object_Type_Name"=>get_TypeName($ObjectType1_Id, 1) ); - @{$CompatProblems{$Interface}{$SubProblemType}{$NewLocation}}{keys(%{$SubProblems{$SubProblemType}{$SubLocation}})} = values %{$SubProblems{$SubProblemType}{$SubLocation}}; - if($SubLocation !~ /\-\>/) - { - $CompatProblems{$Interface}{$SubProblemType}{$NewLocation}{"Start_Type_Name"} = get_TypeName($ObjectType1_Id, 1); - } - } - } - } - } - } - set_Problems_Priority(); -} - -sub getTypeIdByName($$) -{ - my ($TypeName, $Version) = @_; - return $TName_Tid{$Version}{correctName($TypeName)}; -} - -sub detectTypeChange($$$) -{ - my ($Type1_Id, $Type2_Id, $Prefix) = @_; - my %LocalProblems = (); - my $Type1_DId = $Tid_TDid{1}{$Type1_Id}; - my $Type2_DId = $Tid_TDid{2}{$Type2_Id}; - my %Type1 = get_Type($Type1_DId, $Type1_Id, 1); - my %Type2 = get_Type($Type2_DId, $Type2_Id, 2); - my %Type1_Base = get_BaseType($Type1_DId, $Type1_Id, 1); - my %Type2_Base = get_BaseType($Type2_DId, $Type2_Id, 2); - my %Type1_Pure = get_PureType($Type1_DId, $Type1_Id, 1); - my %Type2_Pure = get_PureType($Type2_DId, $Type2_Id, 2); - my $Type1_PointerLevel = get_PointerLevel($Type1_DId, $Type1_Id, 1); - my $Type2_PointerLevel = get_PointerLevel($Type2_DId, $Type2_Id, 2); - return () if(not $Type1{"Name"} or not $Type2{"Name"} or not $Type1{"Size"} or not $Type2{"Size"} or not $Type1_Pure{"Size"} or not $Type2_Pure{"Size"} or not $Type1_Base{"Name"} or not $Type2_Base{"Name"} or not $Type1_Base{"Size"} or not $Type2_Base{"Size"} or $Type1_PointerLevel eq "" or $Type2_PointerLevel eq ""); - if($Type1_Base{"Name"} ne $Type2_Base{"Name"}) - {#base type change - if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/) - { - if($Type1_Base{"Size"}!=$Type2_Base{"Size"}) - { - %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=( - "Old_Value"=>$Type1_Base{"Name"}, - "New_Value"=>$Type2_Base{"Name"}, - "Old_Size"=>$Type1_Base{"Size"}, - "New_Size"=>$Type2_Base{"Size"}, - "InitialType_Type"=>$Type1_Pure{"Type"}); - } - else - { - %{$LocalProblems{$Prefix."_BaseType"}}=( - "Old_Value"=>$Type1_Base{"Name"}, - "New_Value"=>$Type2_Base{"Name"}, - "InitialType_Type"=>$Type1_Pure{"Type"}); - } - } - } - elsif($Type1{"Name"} ne $Type2{"Name"}) - {#type change - if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/) - { - if($Type1{"Size"}!=$Type2{"Size"}) - { - %{$LocalProblems{$Prefix."_Type_And_Size"}}=( - "Old_Value"=>$Type1{"Name"}, - "New_Value"=>$Type2{"Name"}, - "Old_Size"=>($Type1{"Type"} eq "Array")?$Type1{"Size"}*$Type1_Base{"Size"}:$Type1{"Size"}, - "New_Size"=>($Type2{"Type"} eq "Array")?$Type2{"Size"}*$Type2_Base{"Size"}:$Type2{"Size"}, - "InitialType_Type"=>$Type1_Pure{"Type"}); - } - else - { - %{$LocalProblems{$Prefix."_Type"}}=( - "Old_Value"=>$Type1{"Name"}, - "New_Value"=>$Type2{"Name"}, - "InitialType_Type"=>$Type1_Pure{"Type"}); - } - } - } - - if($Type1_PointerLevel!=$Type2_PointerLevel) - { - %{$LocalProblems{$Prefix."_PointerLevel"}}=( - "Old_Value"=>$Type1_PointerLevel, - "New_Value"=>$Type2_PointerLevel); - } - return %LocalProblems; -} - -sub htmlSpecChars($) -{ - my $Str = $_[0]; - $Str =~ s/\&([^#])/&$1/g; - $Str =~ s//>/g; - $Str =~ s/([^ ])( )([^ ])/$1\@ALONE_SP\@$3/g; - $Str =~ s/ / /g; - $Str =~ s/\@ALONE_SP\@/ /g; - $Str =~ s/\n//g; - return $Str; -} - -sub highLight_Signature($) -{ - my $Signature = $_[0]; - return highLight_Signature_PPos_Italic($Signature, "", 0, 0); -} - -sub highLight_Signature_Italic($) -{ - my $Signature = $_[0]; - return highLight_Signature_PPos_Italic($Signature, "", 1, 0); -} - -sub highLight_Signature_Italic_Color($) -{ - my $Signature = $_[0]; - return highLight_Signature_PPos_Italic($Signature, "", 1, 1); -} - -sub highLight_Signature_PPos_Italic($$$$) -{ - my ($FullSignature, $Parameter_Position, $ItalicParams, $ColorParams) = @_; - my ($Signature, $SymbolVersion) = ($FullSignature, ""); - if($FullSignature =~ /\A(.+)[\@]+(.+)\Z/) - { - ($Signature, $SymbolVersion) = ($1, $2); - } - if($Signature=~/\Atypeinfo\W/) - { - return $Signature.(($SymbolVersion)?" \@ $SymbolVersion":""); - } - if($Signature!~/\)(| const)\Z/) - { - return $Signature.(($SymbolVersion)?" \@ $SymbolVersion":""); - } - $Signature =~ /(.+?)\(.*\)(| const)\Z/; - my ($Begin, $End) = ($1, $2); - my @Parts = (); - my $Part_Num = 0; - foreach my $Part (get_Signature_Parts($Signature, 1)) - { - $Part =~ s/\A\s+|\s+\Z//g; - my ($Part_Styled, $ParamName) = ($Part, ""); - if($Part=~/\([\*]+(\w+)\)/i) - {#func-ptr - $ParamName = $1; - } - elsif($Part=~/(\w+)[\,\)]*\Z/i) - { - $ParamName = $1; - } - if(not $ParamName) - { - push(@Parts, $Part); - next; - } - if($ItalicParams and not $TName_Tid{1}{$Part} and not $TName_Tid{2}{$Part}) - { - if(($Parameter_Position ne "") and ($Part_Num == $Parameter_Position)) - { - $Part_Styled =~ s!(\W)$ParamName([\,\)]|\Z)!$1$ParamName$2!ig; - } - elsif($ColorParams) - { - $Part_Styled =~ s!(\W)$ParamName([\,\)]|\Z)!$1$ParamName$2!ig; - } - else - { - $Part_Styled =~ s!(\W)$ParamName([\,\)]|\Z)!$1$ParamName$2!ig; - } - } - $Part_Styled = "".$Part_Styled.""; - push(@Parts, $Part_Styled); - $Part_Num += 1; - } - $Signature = $Begin.""."(".join(" ", @Parts).")"."".$End; - $Signature =~ s!\[\]![]!g; - $Signature =~ s!operator=!operator=!g; - $Signature =~ s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\])!$1!g; - return $Signature.(($SymbolVersion)?" \@ $SymbolVersion":""); -} - -sub get_Signature_Parts($$) -{ - my ($Signature, $Comma) = @_; - my @Parts = (); - my $Bracket_Num = 0; - my $Bracket2_Num = 0; - my $Parameters = $Signature; - if($Signature=~/>|</) - { - $Parameters=~s/>/>/g; - $Parameters=~s/</"); - if($Symbol eq "," and $Bracket_Num==0 and $Bracket2_Num==0) - { - $Parts[$Part_Num] .= $Symbol if($Comma); - $Part_Num += 1; - } - else - { - $Parts[$Part_Num] .= $Symbol; - } - } - if($Signature=~/>|</) - { - foreach my $Part (@Parts) - { - $Part=~s/\>/>/g; - $Part=~s/\1, - "Withdrawn_Virtual_Function"=>1, - "Virtual_Function_Position"=>1, - "Virtual_Function_Redefinition"=>1, - "Virtual_Function_Redefinition_B"=>1, - "Size"=>1, - "Added_Member_And_Size"=>1, - "Added_Middle_Member_And_Size"=>1, - "Withdrawn_Member_And_Size"=>1, - "Withdrawn_Member"=>1, - "Withdrawn_Middle_Member_And_Size"=>1, - "Member_Rename"=>1, - "Enum_Member_Value"=>1, - "Enum_Member_Name"=>1, - "Member_Type_And_Size"=>1, - "Member_Type"=>1, - "Member_BaseType_And_Size"=>1, - "Member_BaseType"=>1, - "Member_PointerLevel"=>1, - "BaseType"=>1 -); - -my %InterfaceProblems_Kind=( - "Added_Interface"=>1, - "Withdrawn_Interface"=>1, - "Function_Become_Static"=>1, - "Function_Become_NonStatic"=>1, - "Parameter_Type_And_Size"=>1, - "Parameter_Type"=>1, - "Parameter_BaseType_And_Size"=>1, - "Parameter_BaseType"=>1, - "Parameter_PointerLevel"=>1, - "Return_Type_And_Size"=>1, - "Return_Type"=>1, - "Return_BaseType_And_Size"=>1, - "Return_BaseType"=>1, - "Return_PointerLevel"=>1, - "Withdrawn_Parameter"=>1, - "Added_Parameter"=>1 -); - -sub testSystem_cpp() -{ - print "testing for C++ library changes\n"; - my (@DataDefs_v1, @Sources_v1, @DataDefs_v2, @Sources_v2) = (); - - #Withdrawn_Parameter - @DataDefs_v1 = (@DataDefs_v1, "int func_withdrawn_parameter(int param, int withdrawn_param);"); - @Sources_v1 = (@Sources_v1, "int func_withdrawn_parameter(int param, int withdrawn_param)\n{\n return 0;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "int func_withdrawn_parameter(int param);"); - @Sources_v2 = (@Sources_v2, "int func_withdrawn_parameter(int param)\n{\n return 0;\n}"); - - #Added_Parameter - @DataDefs_v1 = (@DataDefs_v1, "int func_added_parameter(int param);"); - @Sources_v1 = (@Sources_v1, "int func_added_parameter(int param)\n{\n return 0;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "int func_added_parameter(int param, int added_param);"); - @Sources_v2 = (@Sources_v2, "int func_added_parameter(int param, int added_param)\n{\n return 0;\n}"); - - #Added_Virtual_Function - @DataDefs_v1 = (@DataDefs_v1, "class type_test_added_virtual_function\n{\npublic:\n int func1(int param);\n virtual int func2(int param);\n};"); - @Sources_v1 = (@Sources_v1, "int type_test_added_virtual_function::func1(int param)\n{\n return param;\n}"); - @Sources_v1 = (@Sources_v1, "int type_test_added_virtual_function::func2(int param)\n{\n return param;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "class type_test_added_virtual_function\n{\npublic:\n virtual int func1(int param);\n virtual int func2(int param);\n};"); - @Sources_v2 = (@Sources_v2, "int type_test_added_virtual_function::func1(int param)\n{\n return param;\n}"); - @Sources_v2 = (@Sources_v2, "int type_test_added_virtual_function::func2(int param)\n{\n return param;\n}"); - - #added simple function - @DataDefs_v2 = (@DataDefs_v2, "typedef int (*FUNCPTR_TYPE)(int a, int b);\nint added_function_param_funcptr(FUNCPTR_TYPE*const** f);"); - @Sources_v2 = (@Sources_v2, "int added_function_param_funcptr(FUNCPTR_TYPE*const** f)\n{\n return 0;\n}"); - - #Withdrawn_Virtual_Function - @DataDefs_v1 = (@DataDefs_v1, "class type_test_withdrawn_virtual_function\n{\npublic:\n virtual int func1(int param);\n virtual int func2(int param);\n};"); - @Sources_v1 = (@Sources_v1, "int type_test_withdrawn_virtual_function::func1(int param)\n{\n return param;\n}"); - @Sources_v1 = (@Sources_v1, "int type_test_withdrawn_virtual_function::func2(int param)\n{\n return param;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "class type_test_withdrawn_virtual_function\n{\npublic:\n int func1(int param);\n virtual int func2(int param);\n};"); - @Sources_v2 = (@Sources_v2, "int type_test_withdrawn_virtual_function::func1(int param)\n{\n return param;\n}"); - @Sources_v2 = (@Sources_v2, "int type_test_withdrawn_virtual_function::func2(int param)\n{\n return param;\n}"); - - #Virtual_Function_Position - @DataDefs_v1 = (@DataDefs_v1, "class type_test_virtual_function_position\n{\npublic:\n virtual int func1(int param);\n virtual int func2(int param);\n};"); - @Sources_v1 = (@Sources_v1, "int type_test_virtual_function_position::func1(int param)\n{\n return param;\n}"); - @Sources_v1 = (@Sources_v1, "int type_test_virtual_function_position::func2(int param)\n{\n return param;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "class type_test_virtual_function_position\n{\npublic:\n virtual int func2(int param);\n virtual int func1(int param);\n};"); - @Sources_v2 = (@Sources_v2, "int type_test_virtual_function_position::func1(int param)\n{\n return param;\n}"); - @Sources_v2 = (@Sources_v2, "int type_test_virtual_function_position::func2(int param)\n{\n return param;\n}"); - - #virtual functions safe replace - @DataDefs_v1 = (@DataDefs_v1, "class type_test_virtual_function_position_safe_replace_base\n{\npublic:\n virtual int func1(int param);\n virtual int func2(int param);\n};"); - @Sources_v1 = (@Sources_v1, "int type_test_virtual_function_position_safe_replace_base::func1(int param)\n{\n return param;\n}"); - @Sources_v1 = (@Sources_v1, "int type_test_virtual_function_position_safe_replace_base::func2(int param)\n{\n return param;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "class type_test_virtual_function_position_safe_replace_base\n{\npublic:\n virtual int func1(int param);\n virtual int func2(int param);\n};"); - @Sources_v2 = (@Sources_v2, "int type_test_virtual_function_position_safe_replace_base::func1(int param)\n{\n return param;\n}"); - @Sources_v2 = (@Sources_v2, "int type_test_virtual_function_position_safe_replace_base::func2(int param)\n{\n return param;\n}"); - - @DataDefs_v1 = (@DataDefs_v1, "class type_test_virtual_function_position_safe_replace:public type_test_virtual_function_position_safe_replace_base\n{\npublic:\n virtual int func1(int param);\n virtual int func2(int param);\n};"); - @Sources_v1 = (@Sources_v1, "int type_test_virtual_function_position_safe_replace::func1(int param)\n{\n return param;\n}"); - @Sources_v1 = (@Sources_v1, "int type_test_virtual_function_position_safe_replace::func2(int param)\n{\n return param;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "class type_test_virtual_function_position_safe_replace:public type_test_virtual_function_position_safe_replace_base\n{\npublic:\n virtual int func2(int param);\n virtual int func1(int param);\n};"); - @Sources_v2 = (@Sources_v2, "int type_test_virtual_function_position_safe_replace::func1(int param)\n{\n return param;\n}"); - @Sources_v2 = (@Sources_v2, "int type_test_virtual_function_position_safe_replace::func2(int param)\n{\n return param;\n}"); - - #virtual table changes - @DataDefs_v1 = (@DataDefs_v1, "class type_test_virtual_table_base\n{\npublic:\n virtual int func1(int param);\n virtual int func2(int param);\n};"); - @DataDefs_v1 = (@DataDefs_v1, "class type_test_virtual_table:public type_test_virtual_table_base\n{\npublic:\n virtual int func1(int param);\n virtual int func2(int param);\n};"); - @Sources_v1 = (@Sources_v1, "int type_test_virtual_table_base::func1(int param)\n{\n return param;\n}"); - @Sources_v1 = (@Sources_v1, "int type_test_virtual_table_base::func2(int param)\n{\n return param;\n}"); - @Sources_v1 = (@Sources_v1, "int type_test_virtual_table::func1(int param)\n{\n return param;\n}"); - @Sources_v1 = (@Sources_v1, "int type_test_virtual_table::func2(int param)\n{\n return param;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "class type_test_virtual_table_base\n{\npublic:\n virtual int func1(int param);\n virtual int func2(int param);\n};"); - @DataDefs_v2 = (@DataDefs_v2, "class type_test_virtual_table:public type_test_virtual_table_base\n{\npublic:\n virtual int func2(int param);\n virtual int func1(int param);\n};"); - @Sources_v2 = (@Sources_v2, "int type_test_virtual_table_base::func1(int param)\n{\n return param;\n}"); - @Sources_v2 = (@Sources_v2, "int type_test_virtual_table_base::func2(int param)\n{\n return param;\n}"); - @Sources_v2 = (@Sources_v2, "int type_test_virtual_table::func1(int param)\n{\n return param;\n}"); - @Sources_v2 = (@Sources_v2, "int type_test_virtual_table::func2(int param)\n{\n return param;\n}"); - - #Virtual_Function_Redefinition - @DataDefs_v1 = (@DataDefs_v1, "class type_test_virtual_function_redefinition_base\n{\npublic:\n virtual int func1(int param);\n virtual int func2(int param);\n};"); - @DataDefs_v1 = (@DataDefs_v1, "class type_test_virtual_function_redefinition:public type_test_virtual_function_redefinition_base\n{\npublic:\n virtual int func3(int param);\n};"); - @Sources_v1 = (@Sources_v1, "int type_test_virtual_function_redefinition_base::func1(int param)\n{\n return param;\n}"); - @Sources_v1 = (@Sources_v1, "int type_test_virtual_function_redefinition_base::func2(int param)\n{\n return param;\n}"); - @Sources_v1 = (@Sources_v1, "int type_test_virtual_function_redefinition::func3(int param)\n{\n return param;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "class type_test_virtual_function_redefinition_base\n{\npublic:\n virtual int func1(int param);\n virtual int func2(int param);\n};"); - @DataDefs_v2 = (@DataDefs_v2, "class type_test_virtual_function_redefinition:public type_test_virtual_function_redefinition_base\n{\npublic:\n virtual int func2(int param);\n virtual int func3(int param);\n};"); - @Sources_v2 = (@Sources_v2, "int type_test_virtual_function_redefinition_base::func1(int param){\n return param;\n}"); - @Sources_v2 = (@Sources_v2, "int type_test_virtual_function_redefinition_base::func2(int param){\n return param;\n}"); - @Sources_v2 = (@Sources_v2, "int type_test_virtual_function_redefinition::func2(int param)\n{\n return param;\n}"); - @Sources_v2 = (@Sources_v2, "int type_test_virtual_function_redefinition::func3(int param)\n{\n return param;\n}"); - - #size change - @DataDefs_v1 = (@DataDefs_v1, "struct type_test_size\n{\npublic:\n virtual type_test_size func1(type_test_size param);\n int i;\n long j;\n double k;\n type_test_size* p;\n};"); - @Sources_v1 = (@Sources_v1, "type_test_size type_test_size::func1(type_test_size param)\n{\n return param;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "struct type_test_size\n{\npublic:\n virtual type_test_size func1(type_test_size param);\n int i;\n long j;\n double k;\n type_test_size* p;\n int added_member;\n};"); - @Sources_v2 = (@Sources_v2, "type_test_size type_test_size::func1(type_test_size param)\n{\n return param;\n}"); - - #Added_Member_And_Size - @DataDefs_v1 = (@DataDefs_v1, "struct type_test_added_member\n{\npublic:\n virtual type_test_added_member func1(type_test_added_member param);\n int i;\n long j;\n double k;\n type_test_added_member* p;\n};"); - @Sources_v1 = (@Sources_v1, "type_test_added_member type_test_added_member::func1(type_test_added_member param)\n{\n return param;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "struct type_test_added_member\n{\npublic:\n virtual type_test_added_member func1(type_test_added_member param);\n int i;\n long j;\n double k;\n type_test_added_member* p;\n int added_member;\n};"); - @Sources_v2 = (@Sources_v2, "type_test_added_member type_test_added_member::func1(type_test_added_member param)\n{\n return param;\n}"); - - #Method object changes - @DataDefs_v1 = (@DataDefs_v1, "class type_test_object_added_member\n{\npublic:\n virtual int func1(int param);\n int i;\n long j;\n double k;\n type_test_added_member* p;\n};"); - @Sources_v1 = (@Sources_v1, "int type_test_object_added_member::func1(int param)\n{\n return param;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "class type_test_object_added_member\n{\npublic:\n virtual int func1(int param);\n int i;\n long j;\n double k;\n type_test_added_member* p;\n int added_member;\n};"); - @Sources_v2 = (@Sources_v2, "int type_test_object_added_member::func1(int param)\n{\n return param;\n}"); - - #added bitfield - @DataDefs_v1 = (@DataDefs_v1, "struct type_test_added_bitfield\n{\npublic:\n virtual type_test_added_bitfield func1(type_test_added_bitfield param);\n int i;\n long j;\n double k;\n int b1 : 32;\n int b2 : 31;\n type_test_added_bitfield* p;\n};"); - @Sources_v1 = (@Sources_v1, "type_test_added_bitfield type_test_added_bitfield::func1(type_test_added_bitfield param)\n{\n return param;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "struct type_test_added_bitfield\n{\npublic:\n virtual type_test_added_bitfield func1(type_test_added_bitfield param);\n int i;\n long j;\n double k;\n int b1 : 32;\n int b2 : 31;\n int added_bitfield : 1;\n type_test_added_bitfield* p;\n};"); - @Sources_v2 = (@Sources_v2, "type_test_added_bitfield type_test_added_bitfield::func1(type_test_added_bitfield param)\n{\n return param;\n}"); - - #withdrawn bitfield - @DataDefs_v1 = (@DataDefs_v1, "struct type_test_withdrawn_bitfield\n{\npublic:\n virtual type_test_withdrawn_bitfield func1(type_test_withdrawn_bitfield param);\n int i;\n long j;\n double k;\n int b1 : 32;\n int b2 : 31;\n int withdrawn_bitfield : 1;\n type_test_withdrawn_bitfield* p;\n};"); - @Sources_v1 = (@Sources_v1, "type_test_withdrawn_bitfield type_test_withdrawn_bitfield::func1(type_test_withdrawn_bitfield param)\n{\n return param;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "struct type_test_withdrawn_bitfield\n{\npublic:\n virtual type_test_withdrawn_bitfield func1(type_test_withdrawn_bitfield param);\n int i;\n long j;\n double k;\n int b1 : 32;\n int b2 : 31;\n type_test_withdrawn_bitfield* p;\n};"); - @Sources_v2 = (@Sources_v2, "type_test_withdrawn_bitfield type_test_withdrawn_bitfield::func1(type_test_withdrawn_bitfield param)\n{\n return param;\n}"); - - #Added_Middle_Member_And_Size - @DataDefs_v1 = (@DataDefs_v1, "struct type_test_added_middle_member\n{\npublic:\n virtual type_test_added_middle_member func1(type_test_added_middle_member param);\n int i;\n long j;\n double k;\n type_test_added_middle_member* p;\n};"); - @Sources_v1 = (@Sources_v1, "type_test_added_middle_member type_test_added_middle_member::func1(type_test_added_middle_member param)\n{\n return param;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "struct type_test_added_middle_member\n{\npublic:\n virtual type_test_added_middle_member func1(type_test_added_middle_member param);\n int i;\n int added_middle_member;\n long j;\n double k;\n type_test_added_middle_member* p;\n};"); - @Sources_v2 = (@Sources_v2, "type_test_added_middle_member type_test_added_middle_member::func1(type_test_added_middle_member param)\n{\n return param;\n}"); - - #Member_Rename - @DataDefs_v1 = (@DataDefs_v1, "struct type_test_member_rename\n{\npublic:\n virtual type_test_member_rename func1(type_test_member_rename param);\n long i;\n long j;\n double k;\n type_test_member_rename* p;\n};"); - @Sources_v1 = (@Sources_v1, "type_test_member_rename type_test_member_rename::func1(type_test_member_rename param)\n{\n return param;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "struct type_test_member_rename\n{\npublic:\n virtual type_test_member_rename func1(type_test_member_rename param);\n long renamed_member;\n long j;\n double k;\n type_test_member_rename* p;\n};"); - @Sources_v2 = (@Sources_v2, "type_test_member_rename type_test_member_rename::func1(type_test_member_rename param)\n{\n return param;\n}"); - - #Withdrawn_Member_And_Size - @DataDefs_v1 = (@DataDefs_v1, "struct type_test_withdrawn_member\n{\npublic:\n virtual type_test_withdrawn_member func1(type_test_withdrawn_member param);\n int i;\n long j;\n double k;\n type_test_withdrawn_member* p;\n int withdrawn_member;\n};"); - @Sources_v1 = (@Sources_v1, "type_test_withdrawn_member type_test_withdrawn_member::func1(type_test_withdrawn_member param)\n{\n return param;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "struct type_test_withdrawn_member\n{\npublic:\n virtual type_test_withdrawn_member func1(type_test_withdrawn_member param);\n int i;\n long j;\n double k;\n type_test_withdrawn_member* p;\n};"); - @Sources_v2 = (@Sources_v2, "type_test_withdrawn_member type_test_withdrawn_member::func1(type_test_withdrawn_member param)\n{\n return param;\n}"); - - #Withdrawn_Middle_Member_And_Size - @DataDefs_v1 = (@DataDefs_v1, "struct type_test_withdrawn_middle_member\n{\npublic:\n virtual type_test_withdrawn_middle_member func1(type_test_withdrawn_middle_member param);\n int i;\n int withdrawn_middle_member;\n long j;\n double k;\n type_test_withdrawn_middle_member* p;\n};"); - @Sources_v1 = (@Sources_v1, "type_test_withdrawn_middle_member type_test_withdrawn_middle_member::func1(type_test_withdrawn_middle_member param)\n{\n return param;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "struct type_test_withdrawn_middle_member\n{\npublic:\n virtual type_test_withdrawn_middle_member func1(type_test_withdrawn_middle_member param);\n int i;\n long j;\n double k;\n type_test_withdrawn_middle_member* p;\n};"); - @Sources_v2 = (@Sources_v2, "type_test_withdrawn_middle_member type_test_withdrawn_middle_member::func1(type_test_withdrawn_middle_member param)\n{\n return param;\n}"); - - #Enum_Member_Value - @DataDefs_v1 = (@DataDefs_v1, "enum type_test_enum_member_value_change\n{\n MEMBER_1=1,\n MEMBER_2=2\n};"); - @DataDefs_v1 = (@DataDefs_v1, "int func_test_enum_member_value_change(enum type_test_enum_member_value_change param);"); - @Sources_v1 = (@Sources_v1, -"int func_test_enum_member_value_change(enum type_test_enum_member_value_change param) -{ - switch(param) - { - case 1: - return 1; - case 2: - return 2; - } - return 0; -}"); - - @DataDefs_v2 = (@DataDefs_v2, "enum type_test_enum_member_value_change\n{\n MEMBER_1=2,\n MEMBER_2=1\n};"); - @DataDefs_v2 = (@DataDefs_v2, "int func_test_enum_member_value_change(enum type_test_enum_member_value_change param);"); - @Sources_v2 = (@Sources_v2, -"int func_test_enum_member_value_change(enum type_test_enum_member_value_change param) -{ - switch(param) - { - case 1: - return 1; - case 2: - return 2; - } - return 0; -}"); - - #Enum_Member_Name - @DataDefs_v1 = (@DataDefs_v1, "enum type_test_enum_member_rename\n{\n BRANCH_1=1,\n BRANCH_2=2\n};"); - @DataDefs_v1 = (@DataDefs_v1, "int func_test_enum_member_rename(enum type_test_enum_member_rename param);"); - @Sources_v1 = (@Sources_v1, -"int func_test_enum_member_rename(enum type_test_enum_member_rename param) -{ - switch(param) - { - case 1: - return 1; - case 2: - return 2; - } - return 0; -}"); - - @DataDefs_v2 = (@DataDefs_v2, "enum type_test_enum_member_rename\n{\n BRANCH_FIRST=1,\n BRANCH_SECOND=1\n};"); - @DataDefs_v2 = (@DataDefs_v2, "int func_test_enum_member_rename(enum type_test_enum_member_rename param);"); - @Sources_v2 = (@Sources_v2, -"int func_test_enum_member_rename(enum type_test_enum_member_rename param) -{ - switch(param) - { - case 1: - return 1; - case 2: - return 2; - } - return 0; -}"); - - #Member_Type_And_Size - @DataDefs_v1 = (@DataDefs_v1, "struct type_test_member_type_and_size\n{\npublic:\n type_test_member_type_and_size func1(type_test_member_type_and_size param);\n int i;\n long j;\n double k;\n type_test_member_type_and_size* p;\n};"); - @Sources_v1 = (@Sources_v1, "type_test_member_type_and_size type_test_member_type_and_size::func1(type_test_member_type_and_size param)\n{\n return param;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "struct type_test_member_type_and_size\n{\npublic:\n type_test_member_type_and_size func1(type_test_member_type_and_size param);\n long long i;\n long j;\n double k;\n type_test_member_type_and_size* p;\n};"); - @Sources_v2 = (@Sources_v2, "type_test_member_type_and_size type_test_member_type_and_size::func1(type_test_member_type_and_size param)\n{\n return param;\n}"); - - #Member_Type - @DataDefs_v1 = (@DataDefs_v1, "struct type_test_member_type\n{\npublic:\n type_test_member_type func1(type_test_member_type param);\n int i;\n long j;\n double k;\n type_test_member_type* p;\n};"); - @Sources_v1 = (@Sources_v1, "type_test_member_type type_test_member_type::func1(type_test_member_type param)\n{\n return param;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "struct type_test_member_type\n{\npublic:\n type_test_member_type func1(type_test_member_type param);\n float i;\n long j;\n double k;\n type_test_member_type* p;\n};"); - @Sources_v2 = (@Sources_v2, "type_test_member_type type_test_member_type::func1(type_test_member_type param)\n{\n return param;\n}"); - - #Member_BaseType - @DataDefs_v1 = (@DataDefs_v1, "struct type_test_member_basetype\n{\npublic:\n type_test_member_basetype func1(type_test_member_basetype param);\n int *i;\n long j;\n double k;\n type_test_member_basetype* p;\n};"); - @Sources_v1 = (@Sources_v1, "type_test_member_basetype type_test_member_basetype::func1(type_test_member_basetype param)\n{\n return param;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "struct type_test_member_basetype\n{\npublic:\n type_test_member_basetype func1(type_test_member_basetype param);\n long long *i;\n long j;\n double k;\n type_test_member_basetype* p;\n};"); - @Sources_v2 = (@Sources_v2, "type_test_member_basetype type_test_member_basetype::func1(type_test_member_basetype param)\n{\n return param;\n}"); - - #Member_PointerLevel_And_Size - @DataDefs_v1 = (@DataDefs_v1, "struct type_test_member_pointerlevel_and_size\n{\npublic:\n type_test_member_pointerlevel_and_size func1(type_test_member_pointerlevel_and_size param);\n long long i;\n long j;\n double k;\n type_test_member_pointerlevel_and_size* p;\n};"); - @Sources_v1 = (@Sources_v1, "type_test_member_pointerlevel_and_size type_test_member_pointerlevel_and_size::func1(type_test_member_pointerlevel_and_size param)\n{\n return param;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "struct type_test_member_pointerlevel_and_size\n{\npublic:\n type_test_member_pointerlevel_and_size func1(type_test_member_pointerlevel_and_size param);\n long long *i;\n long j;\n double k;\n type_test_member_pointerlevel_and_size* p;\n};"); - @Sources_v2 = (@Sources_v2, "type_test_member_pointerlevel_and_size type_test_member_pointerlevel_and_size::func1(type_test_member_pointerlevel_and_size param)\n{\n return param;\n}"); - - #Member_PointerLevel - @DataDefs_v1 = (@DataDefs_v1, "struct type_test_member_pointerlevel\n{\npublic:\n type_test_member_pointerlevel func1(type_test_member_pointerlevel param);\n int **i;\n long j;\n double k;\n type_test_member_pointerlevel* p;\n};"); - @Sources_v1 = (@Sources_v1, "type_test_member_pointerlevel type_test_member_pointerlevel::func1(type_test_member_pointerlevel param)\n{\n return param;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "struct type_test_member_pointerlevel\n{\npublic:\n type_test_member_pointerlevel func1(type_test_member_pointerlevel param);\n int *i;\n long j;\n double k;\n type_test_member_pointerlevel* p;\n};"); - @Sources_v2 = (@Sources_v2, "type_test_member_pointerlevel type_test_member_pointerlevel::func1(type_test_member_pointerlevel param)\n{\n return param;\n}"); - - #Added_Interface (function) - @DataDefs_v1 = (@DataDefs_v1, "struct type_test_added_interface\n{\npublic:\n type_test_added_interface func1(type_test_added_interface param);\n int i;\n long j;\n double k;\n type_test_added_interface* p;\n};"); - @Sources_v1 = (@Sources_v1, "type_test_added_interface type_test_added_interface::func1(type_test_added_interface param)\n{\n return param;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "struct type_test_added_interface\n{\npublic:\n type_test_added_interface func1(type_test_added_interface param);\n type_test_added_interface added_func(type_test_added_interface param);\n int i;\n long j;\n double k;\n type_test_added_interface* p;\n};"); - @DataDefs_v2 = (@DataDefs_v2, "int added_func_2(void *** param);"); - @Sources_v2 = (@Sources_v2, "type_test_added_interface type_test_added_interface::func1(type_test_added_interface param)\n{\n return param;\n}"); - @Sources_v2 = (@Sources_v2, "type_test_added_interface type_test_added_interface::added_func(type_test_added_interface param)\n{\n return param;\n}"); - @Sources_v2 = (@Sources_v2, "int added_func_2(void *** param)\n{\n return 0;\n}"); - - #Added_Interface (global variable) - @DataDefs_v1 = (@DataDefs_v1, "struct type_test_added_variable\n{\npublic:\n int func1(type_test_added_variable param);\n int i;\n long j;\n double k;\n type_test_added_variable* p;\n};"); - @Sources_v1 = (@Sources_v1, "int type_test_added_variable::func1(type_test_added_variable param)\n{\n return i;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "struct type_test_added_variable\n{\npublic:\n int func1(type_test_added_variable param);\n static int i;\n long j;\n double k;\n type_test_added_variable* p;\n};"); - @Sources_v2 = (@Sources_v2, "int type_test_added_variable::func1(type_test_added_variable param)\n{\n return type_test_added_variable::i;\n}"); - @Sources_v2 = (@Sources_v2, "int type_test_added_variable::i=0;"); - - #Withdrawn_Interface - @DataDefs_v1 = (@DataDefs_v1, "struct type_test_withdrawn_interface\n{\npublic:\n type_test_withdrawn_interface func1(type_test_withdrawn_interface param);\n type_test_withdrawn_interface withdrawn_func(type_test_withdrawn_interface param);\n int i;\n long j;\n double k;\n type_test_withdrawn_interface* p;\n};"); - @DataDefs_v1 = (@DataDefs_v1, "int withdrawn_func_2(void *** param);"); - @Sources_v1 = (@Sources_v1, "type_test_withdrawn_interface type_test_withdrawn_interface::func1(type_test_withdrawn_interface param)\n{\n return param;\n}"); - @Sources_v1 = (@Sources_v1, "type_test_withdrawn_interface type_test_withdrawn_interface::withdrawn_func(type_test_withdrawn_interface param)\n{\n return param;\n}"); - @Sources_v1 = (@Sources_v1, "int withdrawn_func_2(void *** param)\n{\n return 0;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "struct type_test_withdrawn_interface\n{\npublic:\n type_test_withdrawn_interface func1(type_test_withdrawn_interface param);\n int i;\n long j;\n double k;\n type_test_withdrawn_interface* p;\n};"); - @Sources_v2 = (@Sources_v2, "type_test_withdrawn_interface type_test_withdrawn_interface::func1(type_test_withdrawn_interface param)\n{\n return param;\n}"); - - #Function_Become_Static - @DataDefs_v1 = (@DataDefs_v1, "struct type_test_become_static\n{\npublic:\n type_test_become_static func_become_static(type_test_become_static param);\n int **i;\n long j;\n double k;\n type_test_become_static* p;\n};"); - @Sources_v1 = (@Sources_v1, "type_test_become_static type_test_become_static::func_become_static(type_test_become_static param)\n{\n return param;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "struct type_test_become_static\n{\npublic:\n static type_test_become_static func_become_static(type_test_become_static param);\n int **i;\n long j;\n double k;\n type_test_become_static* p;\n};"); - @Sources_v2 = (@Sources_v2, "type_test_become_static type_test_become_static::func_become_static(type_test_become_static param)\n{\n return param;\n}"); - - #Function_Become_NonStatic - @DataDefs_v1 = (@DataDefs_v1, "struct type_test_become_nonstatic\n{\npublic:\n static type_test_become_nonstatic func_become_nonstatic(type_test_become_nonstatic param);\n int **i;\n long j;\n double k;\n type_test_become_nonstatic* p;\n};"); - @Sources_v1 = (@Sources_v1, "type_test_become_nonstatic type_test_become_nonstatic::func_become_nonstatic(type_test_become_nonstatic param)\n{\n return param;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "struct type_test_become_nonstatic\n{\npublic:\n type_test_become_nonstatic func_become_nonstatic(type_test_become_nonstatic param);\n int **i;\n long j;\n double k;\n type_test_become_nonstatic* p;\n};"); - @Sources_v2 = (@Sources_v2, "type_test_become_nonstatic type_test_become_nonstatic::func_become_nonstatic(type_test_become_nonstatic param)\n{\n return param;\n}"); - - #Parameter_Type_And_Size - @DataDefs_v1 = (@DataDefs_v1, "int func_parameter_type_and_size(int param, int other_param);"); - @Sources_v1 = (@Sources_v1, "int func_parameter_type_and_size(int param, int other_param)\n{\n return other_param;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "int func_parameter_type_and_size(long long param, int other_param);"); - @Sources_v2 = (@Sources_v2, "int func_parameter_type_and_size(long long param, int other_param)\n{\n return other_param;\n}"); - - #Parameter_Type - @DataDefs_v1 = (@DataDefs_v1, "int func_parameter_type(int param, int other_param);"); - @Sources_v1 = (@Sources_v1, "int func_parameter_type(int param, int other_param)\n{\n return other_param;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "int func_parameter_type(float param, int other_param);"); - @Sources_v2 = (@Sources_v2, "int func_parameter_type(float param, int other_param)\n{\n return other_param;\n}"); - - #Parameter_BaseType - @DataDefs_v1 = (@DataDefs_v1, "int func_parameter_basetypechange(int *param);"); - @Sources_v1 = (@Sources_v1, "int func_parameter_basetypechange(int *param)\n{\n return sizeof(*param);\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "int func_parameter_basetypechange(long long *param);"); - @Sources_v2 = (@Sources_v2, "int func_parameter_basetypechange(long long *param)\n{\n return sizeof(*param);\n}"); - - #Parameter_PointerLevel_And_Size - @DataDefs_v1 = (@DataDefs_v1, "long long func_parameter_pointerlevel_and_size(long long param);"); - @Sources_v1 = (@Sources_v1, "long long func_parameter_pointerlevel_and_size(long long param)\n{\n return param;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "long long func_parameter_pointerlevel_and_size(long long *param);"); - @Sources_v2 = (@Sources_v2, "long long func_parameter_pointerlevel_and_size(long long *param)\n{\n return param[5];\n}"); - - #Parameter_PointerLevel - @DataDefs_v1 = (@DataDefs_v1, "int func_parameter_pointerlevel(int *param);"); - @Sources_v1 = (@Sources_v1, "int func_parameter_pointerlevel(int *param)\n{\n return param[5];\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "int func_parameter_pointerlevel(int **param);"); - @Sources_v2 = (@Sources_v2, "int func_parameter_pointerlevel(int **param)\n{\n return param[5][5];\n}"); - - #Return_Type_And_Size - @DataDefs_v1 = (@DataDefs_v1, "int func_return_type_and_size(int param);"); - @Sources_v1 = (@Sources_v1, "int func_return_type_and_size(int param)\n{\n return 2^(sizeof(int)*8-1)-1;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "long long func_return_type_and_size(int param);"); - @Sources_v2 = (@Sources_v2, "long long func_return_type_and_size(int param)\n{\n return 2^(sizeof(long long)*8-1)-1;\n}"); - - #Return_Type - @DataDefs_v1 = (@DataDefs_v1, "int func_return_type(int param);"); - @Sources_v1 = (@Sources_v1, "int func_return_type(int param)\n{\n return 2^(sizeof(int)*8-1)-1;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "float func_return_type(int param);"); - @Sources_v2 = (@Sources_v2, "float func_return_type(int param)\n{\n return 0.7;\n}"); - - #Return_BaseType - @DataDefs_v1 = (@DataDefs_v1, "int *func_return_basetype(int param);"); - @Sources_v1 = (@Sources_v1, "int *func_return_basetype(int param)\n{\n int *x = new int[10];\n return x;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "long long *func_return_basetype(int param);"); - @Sources_v2 = (@Sources_v2, "long long *func_return_basetype(int param)\n{\n long long *x = new long long[10];\n return x;\n}"); - - #Return_PointerLevel_And_Size - @DataDefs_v1 = (@DataDefs_v1, "long long func_return_pointerlevel_and_size(int param);"); - @Sources_v1 = (@Sources_v1, "long long func_return_pointerlevel_and_size(int param)\n{\n return 100;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "long long *func_return_pointerlevel_and_size(int param);"); - @Sources_v2 = (@Sources_v2, "long long *func_return_pointerlevel_and_size(int param)\n{\n long long* x = new long long[10];\n return x;\n}"); - - #Return_PointerLevel - @DataDefs_v1 = (@DataDefs_v1, "int* func_return_pointerlevel(int param);"); - @Sources_v1 = (@Sources_v1, "int* func_return_pointerlevel(int param)\n{\n int* x = new int[10];\n return x;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "int **func_return_pointerlevel(int param);"); - @Sources_v2 = (@Sources_v2, "int **func_return_pointerlevel(int param)\n{\n int** x = new int*[10];\n return x;\n}"); - - #typedef to anon struct - @DataDefs_v1 = (@DataDefs_v1, " -typedef struct -{ -public: - int i; - long j; - double k; -} type_test_anon_typedef; -int func_test_anon_typedef(type_test_anon_typedef param);"); - @Sources_v1 = (@Sources_v1, "int func_test_anon_typedef(type_test_anon_typedef param)\n{\n return 0;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, " -typedef struct -{ -public: - int i; - long j; - double k; - union { - int dummy[256]; - struct { - char q_skiptable[256]; - const char *p; - int l; - } p; - }; -} type_test_anon_typedef; -int func_test_anon_typedef(type_test_anon_typedef param);"); - @Sources_v2 = (@Sources_v2, "int func_test_anon_typedef(type_test_anon_typedef param)\n{\n return 0;\n}"); - - #opaque type - @DataDefs_v1 = (@DataDefs_v1, "struct type_test_opaque\n{\npublic:\n virtual type_test_opaque func1(type_test_opaque param);\n int i;\n long j;\n double k;\n type_test_opaque* p;\n};"); - @Sources_v1 = (@Sources_v1, "type_test_opaque type_test_opaque::func1(type_test_opaque param)\n{\n return param;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "struct type_test_opaque\n{\npublic:\n virtual type_test_opaque func1(type_test_opaque param);\n int i;\n long j;\n double k;\n type_test_opaque* p;\n int added_member;\n};"); - @Sources_v2 = (@Sources_v2, "type_test_opaque type_test_opaque::func1(type_test_opaque param)\n{\n return param;\n}"); - - #internal function - @DataDefs_v1 = (@DataDefs_v1, "struct type_test_internal\n{\npublic:\n virtual type_test_internal func1(type_test_internal param);\n int i;\n long j;\n double k;\n type_test_internal* p;\n};"); - @Sources_v1 = (@Sources_v1, "type_test_internal type_test_internal::func1(type_test_internal param)\n{\n return param;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "struct type_test_internal\n{\npublic:\n virtual type_test_internal func1(type_test_internal param);\n int i;\n long j;\n double k;\n type_test_internal* p;\n int added_member;\n};"); - @Sources_v2 = (@Sources_v2, "type_test_internal type_test_internal::func1(type_test_internal param)\n{\n return param;\n}"); - - #starting versioning - @DataDefs_v1 = (@DataDefs_v1, "int func_return_type_and_start_versioning(int param);"); - @Sources_v1 = (@Sources_v1, "int func_return_type_and_start_versioning(int param)\n{\n return 2^(sizeof(int)*8-1)-1;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "int func_return_type_and_start_versioning(int param);"); - @Sources_v2 = (@Sources_v2, "int func_return_type_and_start_versioning(int param)\n{\n return 2^(sizeof(int)*8-1)-1;\n}\n__asm__(\".symver _Z37func_return_type_and_start_versioningi,_Z37func_return_type_and_start_versioningi\@TEST_2.0\");"); - - #Return_Type And Good Versioning - @DataDefs_v1 = (@DataDefs_v1, "int func_return_type_and_good_versioning(int param);"); - @Sources_v1 = (@Sources_v1, "int func_return_type_and_good_versioning(int param)\n{\n return 2^(sizeof(int)*8-1)-1;\n}\n__asm__(\".symver _Z36func_return_type_and_good_versioningi,_Z36func_return_type_and_good_versioningi\@TEST_1.0\");"); - - @DataDefs_v2 = (@DataDefs_v2, "int func_return_type_and_good_versioning_old(int param);"); - @Sources_v2 = (@Sources_v2, "int func_return_type_and_good_versioning_old(int param)\n{\n return 2^(sizeof(int)*8-1)-1;\n}\n__asm__(\".symver _Z40func_return_type_and_good_versioning_oldi,_Z36func_return_type_and_good_versioningi\@TEST_1.0\");"); - - @DataDefs_v2 = (@DataDefs_v2, "float func_return_type_and_good_versioning(int param);"); - @Sources_v2 = (@Sources_v2, "float func_return_type_and_good_versioning(int param)\n{\n return 0.7;\n}\n__asm__(\".symver _Z36func_return_type_and_good_versioningi,_Z36func_return_type_and_good_versioningi\@TEST_2.0\");"); - - #Return_Type and bad versioning - @DataDefs_v1 = (@DataDefs_v1, "int func_return_type_and_bad_versioning(int param);"); - @Sources_v1 = (@Sources_v1, "int func_return_type_and_bad_versioning(int param)\n{\n return 2^(sizeof(int)*8-1)-1;\n}\n__asm__(\".symver _Z35func_return_type_and_bad_versioningi,_Z35func_return_type_and_bad_versioningi\@TEST_1.0\");"); - - @DataDefs_v2 = (@DataDefs_v2, "float func_return_type_and_bad_versioning_old(int param);"); - @Sources_v2 = (@Sources_v2, "float func_return_type_and_bad_versioning_old(int param)\n{\n return 0.7;\n}\n__asm__(\".symver _Z39func_return_type_and_bad_versioning_oldi,_Z35func_return_type_and_bad_versioningi\@TEST_1.0\");"); - - @DataDefs_v2 = (@DataDefs_v2, "float func_return_type_and_bad_versioning(int param);"); - @Sources_v2 = (@Sources_v2, "float func_return_type_and_bad_versioning(int param)\n{\n return 0.7;\n}\n__asm__(\".symver _Z35func_return_type_and_bad_versioningi,_Z35func_return_type_and_bad_versioningi\@TEST_2.0\");"); - - #unnamed struct fields within structs - @DataDefs_v1 = (@DataDefs_v1, " -typedef struct { - int a; - struct { - int b; - float c; - }; - int d; -} type_test_unnamed; -int func_test_unnamed(type_test_unnamed param);"); - @Sources_v1 = (@Sources_v1, "int func_test_unnamed(type_test_unnamed param)\n{\n return 0;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, " -typedef struct { - int a; - struct { - long double b; - float c; - }; - int d; -} type_test_unnamed; -int func_test_unnamed(type_test_unnamed param);"); - @Sources_v2 = (@Sources_v2, "int func_test_unnamed(type_test_unnamed param)\n{\n return 0;\n}"); - - #constants - @DataDefs_v1 = (@DataDefs_v1, "#define TEST_PUBLIC_CONSTANT \"old_value\""); - @DataDefs_v2 = (@DataDefs_v2, "#define TEST_PUBLIC_CONSTANT \"new_value\""); - - @DataDefs_v1 = (@DataDefs_v1, "#define TEST_PRIVATE_CONSTANT \"old_value\"\n#undef TEST_PRIVATE_CONSTANT"); - @DataDefs_v2 = (@DataDefs_v2, "#define TEST_PRIVATE_CONSTANT \"new_value\"\n#undef TEST_PRIVATE_CONSTANT"); - - #unions - @DataDefs_v1 = (@DataDefs_v1, " -union type_test_union { - int a; - struct { - int b; - float c; - }; - int d; -}; -int func_test_union(type_test_union param);"); - @Sources_v1 = (@Sources_v1, "int func_test_union(type_test_union param)\n{\n return 0;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, " -union type_test_union { - int a; - long double new_member; - struct { - int b; - float c; - }; - int d; -}; -int func_test_union(type_test_union param);"); - @Sources_v2 = (@Sources_v2, "int func_test_union(type_test_union param)\n{\n return 0;\n}"); - - #typedefs - @DataDefs_v1 = (@DataDefs_v1, "typedef float TYPEDEF_TYPE;\nint func_parameter_typedef_change(TYPEDEF_TYPE param);"); - @Sources_v1 = (@Sources_v1, "int func_parameter_typedef_change(TYPEDEF_TYPE param)\n{\n return 1;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "typedef int TYPEDEF_TYPE;\nint func_parameter_typedef_change(TYPEDEF_TYPE param);"); - @Sources_v2 = (@Sources_v2, "int func_parameter_typedef_change(TYPEDEF_TYPE param)\n{\n return 1;\n}"); - - #typedefs in member type - @DataDefs_v1 = (@DataDefs_v1, "typedef float TYPEDEF_TYPE_2;\nstruct type_test_member_typedef_change{\n public:\nTYPEDEF_TYPE_2 m;};\nint func_test_member_typedef_change(type_test_member_typedef_change param);"); - @Sources_v1 = (@Sources_v1, "int func_test_member_typedef_change(type_test_member_typedef_change param)\n{\n return 1;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "typedef int TYPEDEF_TYPE_2;\nstruct type_test_member_typedef_change{\n public:\nTYPEDEF_TYPE_2 m;};\nint func_test_member_typedef_change(type_test_member_typedef_change param);"); - @Sources_v2 = (@Sources_v2, "int func_test_member_typedef_change(type_test_member_typedef_change param)\n{\n return 1;\n}"); - - create_TestSuite("abi_changes_test_cpp", "C++", join("\n\n", @DataDefs_v1), join("\n\n", @Sources_v1), join("\n\n", @DataDefs_v2), join("\n\n", @Sources_v2), "type_test_opaque", "_ZN18type_test_internal5func1ES_"); -} - -sub testSystem_c() -{ - print "\ntesting for C library changes\n"; - my (@DataDefs_v1, @Sources_v1, @DataDefs_v2, @Sources_v2) = (); - - #Withdrawn_Parameter - @DataDefs_v1 = (@DataDefs_v1, "int func_withdrawn_parameter(int param, int withdrawn_param);"); - @Sources_v1 = (@Sources_v1, "int func_withdrawn_parameter(int param, int withdrawn_param)\n{\n return 0;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "int func_withdrawn_parameter(int param);"); - @Sources_v2 = (@Sources_v2, "int func_withdrawn_parameter(int param)\n{\n return 0;\n}"); - - #Added_Parameter - @DataDefs_v1 = (@DataDefs_v1, "int func_added_parameter(int param);"); - @Sources_v1 = (@Sources_v1, "int func_added_parameter(int param)\n{\n return 0;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "int func_added_parameter(int param, int added_param);"); - @Sources_v2 = (@Sources_v2, "int func_added_parameter(int param, int added_param)\n{\n return 0;\n}"); - - #added function with typedef funcptr parameter - @DataDefs_v2 = (@DataDefs_v2, "typedef int (*FUNCPTR_TYPE)(int a, int b);\nint added_function_param_typedef_funcptr(FUNCPTR_TYPE*const** f);"); - @Sources_v2 = (@Sources_v2, "int added_function_param_typedef_funcptr(FUNCPTR_TYPE*const** f)\n{\n return 0;\n}"); - - #added function with funcptr parameter - @DataDefs_v2 = (@DataDefs_v2, "int added_function_param_funcptr(int(*func)(int, int));"); - @Sources_v2 = (@Sources_v2, "int added_function_param_funcptr(int(*func)(int, int))\n{\n return 0;\n}"); - - #added function with no limited parameters - @DataDefs_v2 = (@DataDefs_v2, "int added_function_nolimit_param(float p1, ...);"); - @Sources_v2 = (@Sources_v2, "int added_function_nolimit_param(float p1, ...)\n{\n return 0;\n}"); - - #size change - @DataDefs_v1 = (@DataDefs_v1, "struct type_test_size\n{\n long long i[5];\n long j;\n double k;\n struct type_test_size* p;\n};"); - @DataDefs_v1 = (@DataDefs_v1, "int func_test_type_size(struct type_test_size param, int param_2);"); - @Sources_v1 = (@Sources_v1, "int func_test_type_size(struct type_test_size param, int param_2)\n{\n return param_2;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "struct type_test_size\n{\n long long i[5];\n long long j;\n double k;\n struct type_test_size* p;\n};"); - @DataDefs_v2 = (@DataDefs_v2, "int func_test_type_size(struct type_test_size param, int param_2);"); - @Sources_v2 = (@Sources_v2, "int func_test_type_size(struct type_test_size param, int param_2)\n{\n return param_2;\n}"); - - #Added_Member_And_Size - @DataDefs_v1 = (@DataDefs_v1, "struct type_test_added_member\n{\n int i;\n long j;\n double k;\n struct type_test_added_member* p;\n};"); - @DataDefs_v1 = (@DataDefs_v1, "int func_test_added_member(struct type_test_added_member param, int param_2);"); - @Sources_v1 = (@Sources_v1, "int func_test_added_member(struct type_test_added_member param, int param_2)\n{\n return param_2;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "struct type_test_added_member\n{\n int i;\n long j;\n double k;\n struct type_test_added_member* p;\n int added_member;\n};"); - @DataDefs_v2 = (@DataDefs_v2, "int func_test_added_member(struct type_test_added_member param, int param_2);"); - @Sources_v2 = (@Sources_v2, "int func_test_added_member(struct type_test_added_member param, int param_2)\n{\n return param_2;\n}"); - - #Added_Middle_Member_And_Size - @DataDefs_v1 = (@DataDefs_v1, "struct type_test_added_middle_member\n{\n int i;\n long j;\n double k;\n struct type_test_added_member* p;\n};"); - @DataDefs_v1 = (@DataDefs_v1, "int func_test_added_middle_member(struct type_test_added_middle_member param, int param_2);"); - @Sources_v1 = (@Sources_v1, "int func_test_added_middle_member(struct type_test_added_middle_member param, int param_2)\n{\n return param_2;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "struct type_test_added_middle_member\n{\n int i;\n int added_middle_member;\n long j;\n double k;\n struct type_test_added_member* p;\n};"); - @DataDefs_v2 = (@DataDefs_v2, "int func_test_added_middle_member(struct type_test_added_middle_member param, int param_2);"); - @Sources_v2 = (@Sources_v2, "int func_test_added_middle_member(struct type_test_added_middle_member param, int param_2)\n{\n return param_2;\n}"); - - #Member_Rename - @DataDefs_v1 = (@DataDefs_v1, "struct type_test_member_rename\n{\n long i;\n long j;\n double k;\n struct type_test_member_rename* p;\n};"); - @DataDefs_v1 = (@DataDefs_v1, "int func_test_member_rename(struct type_test_member_rename param, int param_2);"); - @Sources_v1 = (@Sources_v1, "int func_test_member_rename(struct type_test_member_rename param, int param_2)\n{\n return param_2;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "struct type_test_member_rename\n{\n long renamed_member;\n long j;\n double k;\n struct type_test_member_rename* p;\n};"); - @DataDefs_v2 = (@DataDefs_v2, "int func_test_member_rename(struct type_test_member_rename param, int param_2);"); - @Sources_v2 = (@Sources_v2, "int func_test_member_rename(struct type_test_member_rename param, int param_2)\n{\n return param_2;\n}"); - - #Withdrawn_Member_And_Size - @DataDefs_v1 = (@DataDefs_v1, "struct type_test_withdrawn_member\n{\n int i;\n long j;\n double k;\n struct type_test_withdrawn_member* p;\n int withdrawn_member;\n};"); - @DataDefs_v1 = (@DataDefs_v1, "int func_test_withdrawn_member(struct type_test_withdrawn_member param, int param_2);"); - @Sources_v1 = (@Sources_v1, "int func_test_withdrawn_member(struct type_test_withdrawn_member param, int param_2)\n{\n return param_2;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "struct type_test_withdrawn_member\n{\n int i;\n long j;\n double k;\n struct type_test_withdrawn_member* p;\n};"); - @DataDefs_v2 = (@DataDefs_v2, "int func_test_withdrawn_member(struct type_test_withdrawn_member param, int param_2);"); - @Sources_v2 = (@Sources_v2, "int func_test_withdrawn_member(struct type_test_withdrawn_member param, int param_2)\n{\n return param_2;\n}"); - - #Withdrawn_Middle_Member - @DataDefs_v1 = (@DataDefs_v1, "struct type_test_withdrawn_middle_member\n{\n int i;\n int withdrawn_middle_member;\n long j;\n double k;\n struct type_test_withdrawn_middle_member* p;\n};"); - @DataDefs_v1 = (@DataDefs_v1, "int func_test_withdrawn_middle_member(struct type_test_withdrawn_middle_member param, int param_2);"); - @Sources_v1 = (@Sources_v1, "int func_test_withdrawn_middle_member(struct type_test_withdrawn_middle_member param, int param_2)\n{\n return param_2;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "struct type_test_withdrawn_middle_member\n{\n int i;\n long j;\n double k;\n struct type_test_withdrawn_middle_member* p;\n};"); - @DataDefs_v2 = (@DataDefs_v2, "int func_test_withdrawn_middle_member(struct type_test_withdrawn_middle_member param, int param_2);"); - @Sources_v2 = (@Sources_v2, "int func_test_withdrawn_middle_member(struct type_test_withdrawn_middle_member param, int param_2)\n{\n return param_2;\n}"); - - #Enum_Member_Value - @DataDefs_v1 = (@DataDefs_v1, "enum type_test_enum_member_value_change\n{\n MEMBER_1=1,\n MEMBER_2=2\n};"); - @DataDefs_v1 = (@DataDefs_v1, "int func_test_enum_member_value_change(enum type_test_enum_member_value_change param);"); - @Sources_v1 = (@Sources_v1, -"int func_test_enum_member_value_change(enum type_test_enum_member_value_change param) -{ - switch(param) - { - case 1: - return 1; - case 2: - return 2; - } - return 0; -}"); - - @DataDefs_v2 = (@DataDefs_v2, "enum type_test_enum_member_value_change\n{\n MEMBER_1=2,\n MEMBER_2=1\n};"); - @DataDefs_v2 = (@DataDefs_v2, "int func_test_enum_member_value_change(enum type_test_enum_member_value_change param);"); - @Sources_v2 = (@Sources_v2, -"int func_test_enum_member_value_change(enum type_test_enum_member_value_change param) -{ - switch(param) - { - case 1: - return 1; - case 2: - return 2; - } - return 0; -}"); - - #Enum_Member_Name - @DataDefs_v1 = (@DataDefs_v1, "enum type_test_enum_member_rename\n{\n BRANCH_1=1,\n BRANCH_2=2\n};"); - @DataDefs_v1 = (@DataDefs_v1, "int func_test_enum_member_rename(enum type_test_enum_member_rename param);"); - @Sources_v1 = (@Sources_v1, -"int func_test_enum_member_rename(enum type_test_enum_member_rename param) -{ - switch(param) - { - case 1: - return 1; - case 2: - return 2; - } - return 0; -}"); - - @DataDefs_v2 = (@DataDefs_v2, "enum type_test_enum_member_rename\n{\n BRANCH_FIRST=1,\n BRANCH_SECOND=1\n};"); - @DataDefs_v2 = (@DataDefs_v2, "int func_test_enum_member_rename(enum type_test_enum_member_rename param);"); - @Sources_v2 = (@Sources_v2, -"int func_test_enum_member_rename(enum type_test_enum_member_rename param) -{ - switch(param) - { - case 1: - return 1; - case 2: - return 2; - } - return 0; -}"); - - #Member_Type_And_Size - @DataDefs_v1 = (@DataDefs_v1, "struct type_test_member_type_and_size\n{\n int i;\n long j;\n double k;\n struct type_test_member_type_and_size* p;\n};"); - @DataDefs_v1 = (@DataDefs_v1, "int func_test_member_type_and_size(struct type_test_member_type_and_size param, int param_2);"); - @Sources_v1 = (@Sources_v1, "int func_test_member_type_and_size(struct type_test_member_type_and_size param, int param_2)\n{\n return param_2;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "struct type_test_member_type_and_size\n{\n int i;\n long j;\n long double k;\n struct type_test_member_type_and_size* p;\n};"); - @DataDefs_v2 = (@DataDefs_v2, "int func_test_member_type_and_size(struct type_test_member_type_and_size param, int param_2);"); - @Sources_v2 = (@Sources_v2, "int func_test_member_type_and_size(struct type_test_member_type_and_size param, int param_2)\n{\n return param_2;\n}"); - - #Member_Type - @DataDefs_v1 = (@DataDefs_v1, "struct type_test_member_type\n{\n int i;\n long j;\n double k;\n struct type_test_member_type* p;\n};"); - @DataDefs_v1 = (@DataDefs_v1, "int func_test_member_type(struct type_test_member_type param, int param_2);"); - @Sources_v1 = (@Sources_v1, "int func_test_member_type(struct type_test_member_type param, int param_2)\n{\n return param_2;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "struct type_test_member_type\n{\n float i;\n long j;\n double k;\n struct type_test_member_type* p;\n};"); - @DataDefs_v2 = (@DataDefs_v2, "int func_test_member_type(struct type_test_member_type param, int param_2);"); - @Sources_v2 = (@Sources_v2, "int func_test_member_type(struct type_test_member_type param, int param_2)\n{\n return param_2;\n}"); - - #Member_BaseType - @DataDefs_v1 = (@DataDefs_v1, "struct type_test_member_basetype\n{\n int i;\n long *j;\n double k;\n struct type_test_member_basetype* p;\n};"); - @DataDefs_v1 = (@DataDefs_v1, "int func_test_member_basetype(struct type_test_member_basetype param, int param_2);"); - @Sources_v1 = (@Sources_v1, "int func_test_member_basetype(struct type_test_member_basetype param, int param_2)\n{\n return param_2;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "struct type_test_member_basetype\n{\n int i;\n long long *j;\n double k;\n struct type_test_member_basetype* p;\n};"); - @DataDefs_v2 = (@DataDefs_v2, "int func_test_member_basetype(struct type_test_member_basetype param, int param_2);"); - @Sources_v2 = (@Sources_v2, "int func_test_member_basetype(struct type_test_member_basetype param, int param_2)\n{\n return param_2;\n}"); - - #Member_PointerLevel_And_Size - @DataDefs_v1 = (@DataDefs_v1, "struct type_test_member_pointerlevel_and_size\n{\n int i;\n long long j;\n double k;\n struct type_test_member_pointerlevel_and_size* p;\n};"); - @DataDefs_v1 = (@DataDefs_v1, "int func_test_member_pointerlevel_and_size(struct type_test_member_pointerlevel_and_size param, int param_2);"); - @Sources_v1 = (@Sources_v1, "int func_test_member_pointerlevel_and_size(struct type_test_member_pointerlevel_and_size param, int param_2)\n{\n return param_2;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "struct type_test_member_pointerlevel_and_size\n{\n int i;\n long long *j;\n double k;\n struct type_test_member_pointerlevel_and_size* p;\n};"); - @DataDefs_v2 = (@DataDefs_v2, "int func_test_member_pointerlevel_and_size(struct type_test_member_pointerlevel_and_size param, int param_2);"); - @Sources_v2 = (@Sources_v2, "int func_test_member_pointerlevel_and_size(struct type_test_member_pointerlevel_and_size param, int param_2)\n{\n return param_2;\n}"); - - #Member_PointerLevel - @DataDefs_v1 = (@DataDefs_v1, "struct type_test_member_pointerlevel\n{\n int i;\n long *j;\n double k;\n struct type_test_member_pointerlevel* p;\n};"); - @DataDefs_v1 = (@DataDefs_v1, "int func_test_member_pointerlevel(struct type_test_member_pointerlevel param, int param_2);"); - @Sources_v1 = (@Sources_v1, "int func_test_member_pointerlevel(struct type_test_member_pointerlevel param, int param_2)\n{\n return param_2;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "struct type_test_member_pointerlevel\n{\n int i;\n long **j;\n double k;\n struct type_test_member_pointerlevel* p;\n};"); - @DataDefs_v2 = (@DataDefs_v2, "int func_test_member_pointerlevel(struct type_test_member_pointerlevel param, int param_2);"); - @Sources_v2 = (@Sources_v2, "int func_test_member_pointerlevel(struct type_test_member_pointerlevel param, int param_2)\n{\n return param_2;\n}"); - - #Added_Interface - @DataDefs_v2 = (@DataDefs_v2, "int added_func(int param);"); - @Sources_v2 = (@Sources_v2, "int added_func(int param)\n{\n return param;\n}"); - - #Withdrawn_Interface - @DataDefs_v1 = (@DataDefs_v1, "int withdrawn_func(int param);"); - @Sources_v1 = (@Sources_v1, "int withdrawn_func(int param)\n{\n return param;\n}"); - - #Parameter_Type_And_Size - @DataDefs_v1 = (@DataDefs_v1, "int func_parameter_type_and_size(int param, int other_param);"); - @Sources_v1 = (@Sources_v1, "int func_parameter_type_and_size(int param, int other_param)\n{\n return other_param;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "int func_parameter_type_and_size(long long param, int other_param);"); - @Sources_v2 = (@Sources_v2, "int func_parameter_type_and_size(long long param, int other_param)\n{\n return other_param;\n}"); - - #Parameter_Type - @DataDefs_v1 = (@DataDefs_v1, "int func_parameter_type(int param, int other_param);"); - @Sources_v1 = (@Sources_v1, "int func_parameter_type(int param, int other_param)\n{\n return other_param;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "int func_parameter_type(float param, int other_param);"); - @Sources_v2 = (@Sources_v2, "int func_parameter_type(float param, int other_param)\n{\n return other_param;\n}"); - - #Parameter_BaseType (Typedef) - @DataDefs_v1 = (@DataDefs_v1, "typedef int* PARAM_TYPEDEF;\nint func_parameter_basetypechange_typedef(PARAM_TYPEDEF param);"); - @Sources_v1 = (@Sources_v1, "int func_parameter_basetypechange_typedef(PARAM_TYPEDEF param)\n{\n return 0;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "typedef const int* PARAM_TYPEDEF;\nint func_parameter_basetypechange_typedef(PARAM_TYPEDEF param);"); - @Sources_v2 = (@Sources_v2, "int func_parameter_basetypechange_typedef(PARAM_TYPEDEF param)\n{\n return 0;\n}"); - - #Parameter_BaseType - @DataDefs_v1 = (@DataDefs_v1, "int func_parameter_basetypechange(int *param);"); - @Sources_v1 = (@Sources_v1, "int func_parameter_basetypechange(int *param)\n{\n return sizeof(*param);\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "int func_parameter_basetypechange(long long *param);"); - @Sources_v2 = (@Sources_v2, "int func_parameter_basetypechange(long long *param)\n{\n return sizeof(*param);\n}"); - - #Parameter_PointerLevel_And_Size - @DataDefs_v1 = (@DataDefs_v1, "long long func_parameter_pointerlevel_and_size(long long param);"); - @Sources_v1 = (@Sources_v1, "long long func_parameter_pointerlevel_and_size(long long param)\n{\n return param;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "long long func_parameter_pointerlevel_and_size(long long *param);"); - @Sources_v2 = (@Sources_v2, "long long func_parameter_pointerlevel_and_size(long long *param)\n{\n return param[5];\n}"); - - #Parameter_PointerLevel - @DataDefs_v1 = (@DataDefs_v1, "int func_parameter_pointerlevel(int *param);"); - @Sources_v1 = (@Sources_v1, "int func_parameter_pointerlevel(int *param)\n{\n return param[5];\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "int func_parameter_pointerlevel(int **param);"); - @Sources_v2 = (@Sources_v2, "int func_parameter_pointerlevel(int **param)\n{\n return param[5][5];\n}"); - - #Return_Type_And_Size - @DataDefs_v1 = (@DataDefs_v1, "int func_return_type_and_size(int param);"); - @Sources_v1 = (@Sources_v1, "int func_return_type_and_size(int param)\n{\n return 2^(sizeof(int)*8-1)-1;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "long long func_return_type_and_size(int param);"); - @Sources_v2 = (@Sources_v2, "long long func_return_type_and_size(int param)\n{\n return 2^(sizeof(long long)*8-1)-1;\n}"); - - #Return_Type - @DataDefs_v1 = (@DataDefs_v1, "int func_return_type(int param);"); - @Sources_v1 = (@Sources_v1, "int func_return_type(int param)\n{\n return 2^(sizeof(int)*8-1)-1;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "float func_return_type(int param);"); - @Sources_v2 = (@Sources_v2, "float func_return_type(int param)\n{\n return 0.7;\n}"); - - #Return_BaseType - @DataDefs_v1 = (@DataDefs_v1, "int *func_return_basetypechange(int param);"); - @Sources_v1 = (@Sources_v1, "int *func_return_basetypechange(int param)\n{\n int *x = (int*)malloc(10*sizeof(int));\n *x = 2^(sizeof(int)*8-1)-1;\n return x;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "long long *func_return_basetypechange(int param);"); - @Sources_v2 = (@Sources_v2, "long long *func_return_basetypechange(int param)\n{\n long long *x = (long long*)malloc(10*sizeof(long long));\n *x = 2^(sizeof(long long)*8-1)-1;\n return x;\n}"); - - #Return_PointerLevel_And_Size - @DataDefs_v1 = (@DataDefs_v1, "long long func_return_pointerlevel_and_size(int param);"); - @Sources_v1 = (@Sources_v1, "long long func_return_pointerlevel_and_size(int param)\n{\n return 100;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "long long *func_return_pointerlevel_and_size(int param);"); - @Sources_v2 = (@Sources_v2, "long long *func_return_pointerlevel_and_size(int param)\n{\n long long *x = (long long*)malloc(10*sizeof(long long));\n *x = 2^(sizeof(long long)*8-1)-1;\n return x;\n}"); - - #Return_PointerLevel - @DataDefs_v1 = (@DataDefs_v1, "long long *func_return_pointerlevel(int param);"); - @Sources_v1 = (@Sources_v1, "long long *func_return_pointerlevel(int param)\n{\n long long *x = (long long*)malloc(10*sizeof(long long));\n *x = 2^(sizeof(long long)*8-1)-1;\n return x;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "long long **func_return_pointerlevel(int param);"); - @Sources_v2 = (@Sources_v2, "long long **func_return_pointerlevel(int param)\n{\n long long *x = (long long*)malloc(10*sizeof(long long));\n *x = 2^(sizeof(long long)*8-1)-1;\n long *y = (long*)malloc(sizeof(long long));\n *y=(long)&x;\n return (long long **)y;\n}"); - - #typedef to anon struct - @DataDefs_v1 = (@DataDefs_v1, " -typedef struct -{ - int i; - long j; - double k; -} type_test_anon_typedef; -int func_test_anon_typedef(type_test_anon_typedef param);"); - @Sources_v1 = (@Sources_v1, "int func_test_anon_typedef(type_test_anon_typedef param)\n{\n return 0;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, " -typedef struct -{ - int i; - long j; - double k; - union { - int dummy[256]; - struct { - char q_skiptable[256]; - const char *p; - int l; - } p; - }; -} type_test_anon_typedef; -int func_test_anon_typedef(type_test_anon_typedef param);"); - @Sources_v2 = (@Sources_v2, "int func_test_anon_typedef(type_test_anon_typedef param)\n{\n return 0;\n}"); - - #opaque type - @DataDefs_v1 = (@DataDefs_v1, "struct type_test_opaque\n{\n long long i[5];\n long j;\n double k;\n struct type_test_opaque* p;\n};"); - @DataDefs_v1 = (@DataDefs_v1, "int func_test_opaque(struct type_test_opaque param, int param_2);"); - @Sources_v1 = (@Sources_v1, "int func_test_opaque(struct type_test_opaque param, int param_2)\n{\n return param_2;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "struct type_test_opaque\n{\n long long i[5];\n long long j;\n double k;\n struct type_test_opaque* p;\n};"); - @DataDefs_v2 = (@DataDefs_v2, "int func_test_opaque(struct type_test_opaque param, int param_2);"); - @Sources_v2 = (@Sources_v2, "int func_test_opaque(struct type_test_opaque param, int param_2)\n{\n return param_2;\n}"); - - #internal function - @DataDefs_v1 = (@DataDefs_v1, "struct type_test_internal\n{\n long long i[5];\n long j;\n double k;\n struct type_test_internal* p;\n};"); - @DataDefs_v1 = (@DataDefs_v1, "int func_test_internal(struct type_test_internal param, int param_2);"); - @Sources_v1 = (@Sources_v1, "int func_test_internal(struct type_test_internal param, int param_2)\n{\n return param_2;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "struct type_test_internal\n{\n long long i[5];\n long long j;\n double k;\n struct type_test_internal* p;\n};"); - @DataDefs_v2 = (@DataDefs_v2, "int func_test_internal(struct type_test_internal param, int param_2);"); - @Sources_v2 = (@Sources_v2, "int func_test_internal(struct type_test_internal param, int param_2)\n{\n return param_2;\n}"); - - #starting versioning - @DataDefs_v1 = (@DataDefs_v1, "int func_return_type_and_start_versioning(int param);"); - @Sources_v1 = (@Sources_v1, "int func_return_type_and_start_versioning(int param)\n{\n return 2^(sizeof(int)*8-1)-1;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "int func_return_type_and_start_versioning(int param);"); - @Sources_v2 = (@Sources_v2, "int func_return_type_and_start_versioning(int param)\n{\n return 2^(sizeof(int)*8-1)-1;\n}\n__asm__(\".symver func_return_type_and_start_versioning,func_return_type_and_start_versioning\@TEST_2.0\");"); - - #Return_Type and good versioning - @DataDefs_v1 = (@DataDefs_v1, "int func_return_type_and_good_versioning(int param);"); - @Sources_v1 = (@Sources_v1, "int func_return_type_and_good_versioning(int param)\n{\n return 2^(sizeof(int)*8-1)-1;\n}\n__asm__(\".symver func_return_type_and_good_versioning,func_return_type_and_good_versioning\@TEST_1.0\");"); - - @DataDefs_v2 = (@DataDefs_v2, "int func_return_type_and_good_versioning_old(int param);"); - @Sources_v2 = (@Sources_v2, "int func_return_type_and_good_versioning_old(int param)\n{\n return 2^(sizeof(int)*8-1)-1;\n}\n__asm__(\".symver func_return_type_and_good_versioning_old,func_return_type_and_good_versioning\@TEST_1.0\");"); - - @DataDefs_v2 = (@DataDefs_v2, "float func_return_type_and_good_versioning(int param);"); - @Sources_v2 = (@Sources_v2, "float func_return_type_and_good_versioning(int param)\n{\n return 0.7;\n}\n__asm__(\".symver func_return_type_and_good_versioning,func_return_type_and_good_versioning\@TEST_2.0\");"); - - #Return_Type and bad versioning - @DataDefs_v1 = (@DataDefs_v1, "int func_return_type_and_bad_versioning(int param);"); - @Sources_v1 = (@Sources_v1, "int func_return_type_and_bad_versioning(int param)\n{\n return 2^(sizeof(int)*8-1)-1;\n}\n__asm__(\".symver func_return_type_and_bad_versioning,func_return_type_and_bad_versioning\@TEST_1.0\");"); - - @DataDefs_v2 = (@DataDefs_v2, "float func_return_type_and_bad_versioning_old(int param);"); - @Sources_v2 = (@Sources_v2, "float func_return_type_and_bad_versioning_old(int param)\n{\n return 0.7;\n}\n__asm__(\".symver func_return_type_and_bad_versioning_old,func_return_type_and_bad_versioning\@TEST_1.0\");"); - - @DataDefs_v2 = (@DataDefs_v2, "float func_return_type_and_bad_versioning(int param);"); - @Sources_v2 = (@Sources_v2, "float func_return_type_and_bad_versioning(int param)\n{\n return 0.7;\n}\n__asm__(\".symver func_return_type_and_bad_versioning,func_return_type_and_bad_versioning\@TEST_2.0\");"); - - #unnamed struct/union fields within structs/unions - @DataDefs_v1 = (@DataDefs_v1, " -typedef struct { - int a; - union { - int b; - float c; - }; - int d; -} type_test_unnamed; -int func_test_unnamed(type_test_unnamed param);"); - @Sources_v1 = (@Sources_v1, "int func_test_unnamed(type_test_unnamed param)\n{\n return 0;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, " -typedef struct { - int a; - union { - long double b; - float c; - }; - int d; -} type_test_unnamed; -int func_test_unnamed(type_test_unnamed param);"); - @Sources_v2 = (@Sources_v2, "int func_test_unnamed(type_test_unnamed param)\n{\n return 0;\n}"); - - #constants - @DataDefs_v1 = (@DataDefs_v1, "#define TEST_PUBLIC_CONSTANT \"old_value\""); - @DataDefs_v2 = (@DataDefs_v2, "#define TEST_PUBLIC_CONSTANT \"new_value\""); - - @DataDefs_v1 = (@DataDefs_v1, "#define TEST_PRIVATE_CONSTANT \"old_value\"\n#undef TEST_PRIVATE_CONSTANT"); - @DataDefs_v2 = (@DataDefs_v2, "#define TEST_PRIVATE_CONSTANT \"new_value\"\n#undef TEST_PRIVATE_CONSTANT"); - - #anon ptr typedef - @DataDefs_v1 = (@DataDefs_v1, " -#ifdef __cplusplus -extern \"C\" { -#endif -typedef struct { - int a; -} *type_test_anonptr_typedef; -extern __attribute__ ((visibility(\"default\"))) int func_test_anonptr_typedef(type_test_anonptr_typedef param); -#ifdef __cplusplus -} -#endif"); - @Sources_v1 = (@Sources_v1, "__attribute__ ((visibility(\"default\"))) int func_test_anonptr_typedef(type_test_anonptr_typedef param)\n{\n return 0;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, " -#ifdef __cplusplus -extern \"C\" { -#endif -typedef struct { - float a; -} *type_test_anonptr_typedef; -extern __attribute__ ((visibility(\"default\"))) int func_test_anonptr_typedef(type_test_anonptr_typedef param); -#ifdef __cplusplus -} -#endif"); - @Sources_v2 = (@Sources_v2, "__attribute__ ((visibility(\"default\"))) int func_test_anonptr_typedef(type_test_anonptr_typedef param)\n{\n return 0;\n}"); - - #typedefs - @DataDefs_v1 = (@DataDefs_v1, "typedef float TYPEDEF_TYPE;\nint func_parameter_typedef_change(TYPEDEF_TYPE param);"); - @Sources_v1 = (@Sources_v1, "int func_parameter_typedef_change(TYPEDEF_TYPE param)\n{\n return 1.0;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "typedef int TYPEDEF_TYPE;\nint func_parameter_typedef_change(TYPEDEF_TYPE param);"); - @Sources_v2 = (@Sources_v2, "int func_parameter_typedef_change(TYPEDEF_TYPE param)\n{\n return 1;\n}"); - - #typedefs in member type - @DataDefs_v1 = (@DataDefs_v1, "typedef float TYPEDEF_TYPE_2;\nstruct type_test_member_typedef_change{\nTYPEDEF_TYPE_2 m;};\nint func_test_member_typedef_change(struct type_test_member_typedef_change param);"); - @Sources_v1 = (@Sources_v1, "int func_test_member_typedef_change(struct type_test_member_typedef_change param)\n{\n return 1;\n}"); - - @DataDefs_v2 = (@DataDefs_v2, "typedef int TYPEDEF_TYPE_2;\nstruct type_test_member_typedef_change{\nTYPEDEF_TYPE_2 m;};\nint func_test_member_typedef_change(struct type_test_member_typedef_change param);"); - @Sources_v2 = (@Sources_v2, "int func_test_member_typedef_change(struct type_test_member_typedef_change param)\n{\n return 1;\n}"); - - create_TestSuite("abi_changes_test_c", "C", join("\n\n", @DataDefs_v1), join("\n\n", @Sources_v1), join("\n\n", @DataDefs_v2), join("\n\n", @Sources_v2), "type_test_opaque", "func_test_internal"); -} - -sub create_TestSuite($$$$$$$$) -{ - my ($Dir, $Lang, $DataDefs_v1, $Sources_v1, $DataDefs_v2, $Sources_v2, $Opaque, $Private) = @_; - my $Ext = ($Lang eq "C++")?"cpp":"c"; - my $Gcc = ($Lang eq "C++")?"g++":"gcc"; - #creating test suite - my $Path_v1 = "$Dir/lib_abi_changes_test.v1"; - my $Path_v2 = "$Dir/lib_abi_changes_test.v2"; - - system("rm", "-fr", $Path_v1, $Path_v2); - system("mkdir", "-p", $Path_v1, $Path_v2); - - writeFile("$Path_v1/version", "TEST_1.0 {\n};\nTEST_2.0 {\n};\n"); - writeFile("$Path_v1/lib_abi_changes_test.h", "#include \n".$DataDefs_v1."\n"); - writeFile("$Path_v1/lib_abi_changes_test.$Ext", "#include \"lib_abi_changes_test.h\"\n".$Sources_v1."\n"); - writeFile("$Dir/descriptor.v1", "\n 1.0.0\n\n\n\n ".$ENV{"PWD"}."/$Path_v1/\n\n\n\n ".$ENV{"PWD"}."/$Path_v1/\n\n\n\n $Opaque\n\n\n\n $Private\n\n\n\n ".$ENV{"PWD"}."/$Path_v1\n\n"); - - writeFile("$Path_v2/version", "TEST_1.0 {\n};\nTEST_2.0 {\n};\n"); - writeFile("$Path_v2/lib_abi_changes_test.h", "#include \n".$DataDefs_v2."\n"); - writeFile("$Path_v2/lib_abi_changes_test.$Ext", "#include \"lib_abi_changes_test.h\"\n".$Sources_v2."\n"); - writeFile("$Dir/descriptor.v2", "\n 2.0.0\n\n\n\n ".$ENV{"PWD"}."/$Path_v2/\n\n\n\n ".$ENV{"PWD"}."/$Path_v2/\n\n\n\n $Opaque\n\n\n\n $Private\n\n\n\n ".$ENV{"PWD"}."/$Path_v2\n\n"); - - system("$Gcc $Path_v1/lib_abi_changes_test.h"); - if($?) - { - print "ERROR: can't compile \'$Path_v1/lib_abi_changes_test.h\'\n"; - return; - } - system("$Gcc -Wl,--version-script $Path_v1/version -shared $Path_v1/lib_abi_changes_test.$Ext -o $Path_v1/lib_abi_changes_test.so"); - if($?) - { - print "ERROR: can't compile \'$Path_v1/lib_abi_changes_test.$Ext\'\n"; - return; - } - system("$Gcc $Path_v2/lib_abi_changes_test.h"); - if($?) - { - print "ERROR: can't compile \'$Path_v2/lib_abi_changes_test.h\'\n"; - return; - } - system("$Gcc -Wl,--version-script $Path_v2/version -shared $Path_v2/lib_abi_changes_test.$Ext -o $Path_v2/lib_abi_changes_test.so"); - if($?) - { - print "ERROR: can't compile \'$Path_v2/lib_abi_changes_test.$Ext\'\n"; - return; - } - - #running abi-compliance-checker - system("$0 -l lib_$Dir -d1 $Dir/descriptor.v1 -d2 $Dir/descriptor.v2"); -} - -sub writeFile($$) -{ - my ($Path, $Content) = @_; - return if(not $Path); - open (FILE, ">".$Path) || die ("Can't open file $Path\n"); - print FILE $Content; - close(FILE); -} - -sub readFile($) -{ - my $Path = $_[0]; - return "" if(not $Path or not -f $Path); - open (FILE, $Path); - my $Content = join("\n", ); - close(FILE); - return toUnix($Content); -} - -sub toUnix($) -{ - my $Text = $_[0]; - $Text=~s/\r//g; - return $Text; -} - -sub getArch() -{ - my $Arch = $ENV{"CPU"}; - if(not $Arch) - { - $Arch = `uname -m`; - chomp($Arch); - } - if(not $Arch) - { - $Arch = `uname -p`; - chomp($Arch); - } - $Arch = "x86" if($Arch =~ /i[3-7]86/); - return $Arch; -} - -sub get_Report_Header() -{ - my $Report_Header = "

ABI compliance report for the library $TargetLibraryName from version ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." on ".getArch()." ".(($AppPath)?"relating to the portability of application ".get_FileName($AppPath)."":"")."

\n"; - return "\n".$Report_Header."\n"; -} - -sub get_SourceInfo() -{ - my $CheckedHeaders = "\n

Checked header files (".keys(%{$Headers{1}}).")


\n"; - foreach my $Header_Dest (sort {lc($Headers{1}{$a}{"Name"}) cmp lc($Headers{1}{$b}{"Name"})} keys(%{$Headers{1}})) - { - my $Header_Name = $Headers{1}{$Header_Dest}{"Name"}; - my $Dest_Count = keys(%{$HeaderName_Destinations{1}{$Header_Name}}); - my $Identity = $Headers{1}{$Header_Dest}{"Identity"}; - my $Dest_Comment = ($Dest_Count>1 and $Identity=~/\//)?" ($Identity)":""; - $CheckedHeaders .= "$Header_Name"."$Dest_Comment
\n"; - } - $CheckedHeaders .= "
to the top
\n"; - my $CheckedLibs = "\n

Checked shared objects (".keys(%{$SoNames_All{1}}).")


\n"; - foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$SoNames_All{1}})) - { - $CheckedLibs .= "$Library
\n"; - } - $CheckedLibs .= "
to the top
\n"; - return $CheckedHeaders.$CheckedLibs; -} - -sub get_TypeProblems_Count($$) -{ - my ($TypeChanges, $TargetPriority) = @_; - my $Type_Problems_Count = 0; - foreach my $TypeName (sort keys(%{$TypeChanges})) - { - my %Kinds_Target = (); - foreach my $Kind (keys(%{$TypeChanges->{$TypeName}})) - { - foreach my $Location (keys(%{$TypeChanges->{$TypeName}{$Kind}})) - { - my $Priority = $TypeChanges->{$TypeName}{$Kind}{$Location}{"Priority"}; - next if($Priority ne $TargetPriority); - my $Target = $TypeChanges->{$TypeName}{$Kind}{$Location}{"Target"}; - next if($Kinds_Target{$Kind}{$Target}); - $Kinds_Target{$Kind}{$Target} = 1; - $Type_Problems_Count += 1; - } - } - } - return $Type_Problems_Count; -} - -sub get_Summary() -{ - my ($Added, $Withdrawn, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High, $T_Problems_Medium, $T_Problems_Low) = (0,0,0,0,0,0,0,0); - foreach my $Interface (sort keys(%CompatProblems)) - { - foreach my $Kind (sort keys(%{$CompatProblems{$Interface}})) - { - if($InterfaceProblems_Kind{$Kind}) - { - foreach my $Location (sort keys(%{$CompatProblems{$Interface}{$Kind}})) - { - if($Kind eq "Added_Interface") - { - $Added += 1; - } - elsif($Kind eq "Withdrawn_Interface") - { - $Withdrawn += 1; - } - else - { - if($CompatProblems{$Interface}{$Kind}{$Location}{"Priority"} eq "High") - { - $I_Problems_High += 1; - } - elsif($CompatProblems{$Interface}{$Kind}{$Location}{"Priority"} eq "Medium") - { - $I_Problems_Medium += 1; - } - elsif($CompatProblems{$Interface}{$Kind}{$Location}{"Priority"} eq "Low") - { - $I_Problems_Low += 1; - } - } - } - } - } - } - - my (%TypeChanges, %Type_MaxPriority); - foreach my $Interface (sort keys(%CompatProblems)) - { - foreach my $Kind (keys(%{$CompatProblems{$Interface}})) - { - if($TypeProblems_Kind{$Kind}) - { - foreach my $Location (keys(%{$CompatProblems{$Interface}{$Kind}})) - { - my $Type_Name = $CompatProblems{$Interface}{$Kind}{$Location}{"Type_Name"}; - my $Priority = $CompatProblems{$Interface}{$Kind}{$Location}{"Priority"}; - %{$TypeChanges{$Type_Name}{$Kind}{$Location}} = %{$CompatProblems{$Interface}{$Kind}{$Location}}; - $Type_MaxPriority{$Type_Name}{$Kind} = max_priority($Type_MaxPriority{$Type_Name}{$Kind}, $Priority); - } - } - } - } - - foreach my $Type_Name (keys(%TypeChanges)) - { - foreach my $Kind (keys(%{$TypeChanges{$Type_Name}})) - { - foreach my $Location (keys(%{$TypeChanges{$Type_Name}{$Kind}})) - { - my $Priority = $TypeChanges{$Type_Name}{$Kind}{$Location}{"Priority"}; - if(cmp_priority($Type_MaxPriority{$Type_Name}{$Kind}, $Priority)) - { - delete($TypeChanges{$Type_Name}{$Kind}{$Location}); - } - } - } - } - - $T_Problems_High = get_TypeProblems_Count(\%TypeChanges, "High"); - $T_Problems_Medium = get_TypeProblems_Count(\%TypeChanges, "Medium"); - $T_Problems_Low = get_TypeProblems_Count(\%TypeChanges, "Low"); - - #summary - my $Summary = "

Summary


"; - $Summary .= ""; - - - my $Checked_Headers_Link = "0"; - $Checked_Headers_Link = "".keys(%{$Headers{1}})."" if(keys(%{$Headers{1}})>0); - $Summary .= ""; - - my $Checked_Libs_Link = "0"; - $Checked_Libs_Link = "".keys(%{$SoNames_All{1}})."" if(keys(%{$SoNames_All{1}})>0); - $Summary .= ""; - $Summary .= ""; - - my $Verdict = "Compatible"; - $Verdict = "Incompatible" if(($Withdrawn>0) or ($I_Problems_High>0) or ($T_Problems_High>0)); - $Summary .= ""; - - $Summary .= "
Total header files checked$Checked_Headers_Link
Total shared objects checked$Checked_Libs_Link
Total interfaces / types checked".keys(%CheckedInterfaces)." / ".keys(%CheckedTypes)."
Verdict$Verdict
\n"; - - #problem summary - my $Problem_Summary = "

Problem Summary


"; - $Problem_Summary .= ""; - - my $Added_Link = "0"; - $Added_Link = "$Added" if($Added>0); - $Problem_Summary .= ""; - - my $WIthdrawn_Link = "0"; - $WIthdrawn_Link = "$Withdrawn" if($Withdrawn>0); - $Problem_Summary .= ""; - - my $TH_Link = "0"; - $TH_Link = "$T_Problems_High" if($T_Problems_High>0); - $Problem_Summary .= ""; - - my $TM_Link = "0"; - $TM_Link = "$T_Problems_Medium" if($T_Problems_Medium>0); - $Problem_Summary .= ""; - - my $TL_Link = "0"; - $TL_Link = "$T_Problems_Low" if($T_Problems_Low>0); - $Problem_Summary .= ""; - - my $IH_Link = "0"; - $IH_Link = "$I_Problems_High" if($I_Problems_High>0); - $Problem_Summary .= ""; - - my $IM_Link = "0"; - $IM_Link = "$I_Problems_Medium" if($I_Problems_Medium>0); - $Problem_Summary .= ""; - - my $IL_Link = "0"; - $IL_Link = "$I_Problems_Low" if($I_Problems_Low>0); - $Problem_Summary .= ""; - - my $ChangedConstants_Link = "0"; - $ChangedConstants_Link = "".keys(%ConstantProblems)."" if(keys(%ConstantProblems)>0); - $Problem_Summary .= ""; - - $Problem_Summary .= "
Added interfaces$Added_Link
Withdrawn interfaces$WIthdrawn_Link
Problems in
Data Types
High risk$TH_Link
Medium risk$TM_Link
Low risk$TL_Link
Interface
problems
High risk$IH_Link
Medium risk$IM_Link
Low risk$IL_Link
Constants Problems$ChangedConstants_Link
\n"; - return "\n".$Summary.$Problem_Summary."\n"; -} - -sub get_Report_ChangedConstants() -{ - my ($CHANGED_CONSTANTS, %HeaderConstant); - foreach my $Name (keys(%ConstantProblems)) - { - $HeaderConstant{$ConstantProblems{$Name}{"Header"}}{$Name} = 1; - } - my $Constants_Number = 0; - foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%HeaderConstant)) - { - $CHANGED_CONSTANTS .= "$HeaderName
\n"; - foreach my $Name (sort {lc($a) cmp lc($b)} keys(%{$HeaderConstant{$HeaderName}})) - { - $Constants_Number += 1; - my $Old_Value = htmlSpecChars($ConstantProblems{$Name}{"Old_Value"}); - my $New_Value = htmlSpecChars($ConstantProblems{$Name}{"New_Value"}); - my $Incompatibility = "The value of constant $Name has been changed from $Old_Value to $New_Value."; - my $Effect = "If application uses this constant as a parameter of some interface than its execution may change."; - my $ConstantProblemsReport = "1".$Incompatibility."$Effect\n"; - $CHANGED_CONSTANTS .= $ContentSpanStart."[+] ".$Name.$ContentSpanEnd."
\n$ContentDivStart$ConstantProblemsReport
IncompatibilityEffect

$ContentDivEnd\n"; - $CHANGED_CONSTANTS = insertIDs($CHANGED_CONSTANTS); - } - $CHANGED_CONSTANTS .= "
\n"; - } - if($CHANGED_CONSTANTS) - { - $CHANGED_CONSTANTS = "

Constants Problems ($Constants_Number)


\n"."\n".$CHANGED_CONSTANTS."\n"."to the top
\n"; - } - return $CHANGED_CONSTANTS; -} - -sub get_Report_Added() -{ - my $ADDED_INTERFACES; - #added interfaces - my %FuncAddedInHeaderLib; - foreach my $Interface (sort keys(%CompatProblems)) - { - foreach my $Kind (sort keys(%{$CompatProblems{$Interface}})) - { - foreach my $Location (sort keys(%{$CompatProblems{$Interface}{$Kind}})) - { - if($Kind eq "Added_Interface") - { - $FuncAddedInHeaderLib{$CompatProblems{$Interface}{$Kind}{$Location}{"Header"}}{$CompatProblems{$Interface}{$Kind}{$Location}{"New_SoName"}}{$Interface} = 1; - last; - } - } - } - } - my $Added_Number = 0; - foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%FuncAddedInHeaderLib)) - { - foreach my $SoName (sort {lc($a) cmp lc($b)} keys(%{$FuncAddedInHeaderLib{$HeaderName}})) - { - if($HeaderName) - { - $ADDED_INTERFACES .= "$HeaderName, $SoName
\n"; - } - else - { - $ADDED_INTERFACES .= "$SoName
\n"; - } - foreach my $Interface (sort {lc($CompatProblems{$a}{"Added_Interface"}{"SharedLibrary"}{"Signature"}) cmp lc($CompatProblems{$b}{"Added_Interface"}{"SharedLibrary"}{"Signature"})} keys(%{$FuncAddedInHeaderLib{$HeaderName}{$SoName}})) - { - $Added_Number += 1; - my $SubReport = ""; - my $Signature = $CompatProblems{$Interface}{"Added_Interface"}{"SharedLibrary"}{"Signature"}; - if($Interface =~ /\A_Z/) - { - if($Signature) - { - $SubReport = insertIDs($ContentSpanStart.highLight_Signature_Italic_Color(htmlSpecChars($Signature)).$ContentSpanEnd."
\n".$ContentDivStart."[ symbol: $Interface ]

".$ContentDivEnd."\n"); - } - else - { - $SubReport = "".$Interface.""."
\n"; - } - } - else - { - if($Signature) - { - $SubReport = "".highLight_Signature_Italic_Color($Signature).""."
\n"; - } - else - { - $SubReport = "".$Interface.""."
\n"; - } - } - $ADDED_INTERFACES .= $SubReport; - } - $ADDED_INTERFACES .= "
\n"; - } - } - if($ADDED_INTERFACES) - { - $ADDED_INTERFACES = "

Added Interfaces ($Added_Number)


\n"."\n".$ADDED_INTERFACES."\n"."to the top
\n"; - } - return $ADDED_INTERFACES; -} - -sub get_Report_Withdrawn() -{ - my $WITHDRAWN_INTERFACES; - #withdrawn interfaces - my %FuncWithdrawnFromHeaderLib; - foreach my $Interface (sort keys(%CompatProblems)) - { - foreach my $Kind (sort keys(%{$CompatProblems{$Interface}})) - { - foreach my $Location (sort keys(%{$CompatProblems{$Interface}{$Kind}})) - { - if($Kind eq "Withdrawn_Interface") - { - $FuncWithdrawnFromHeaderLib{$CompatProblems{$Interface}{$Kind}{$Location}{"Header"}}{$CompatProblems{$Interface}{$Kind}{$Location}{"Old_SoName"}}{$Interface} = 1; - last; - } - } - } - } - my $Withdrawn_Number = 0; - foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%FuncWithdrawnFromHeaderLib)) - { - foreach my $SoName (sort {lc($a) cmp lc($b)} keys(%{$FuncWithdrawnFromHeaderLib{$HeaderName}})) - { - if($HeaderName) - { - $WITHDRAWN_INTERFACES .= "$HeaderName, $SoName
\n"; - } - else - { - $WITHDRAWN_INTERFACES .= "$SoName
\n"; - } - foreach my $Interface (sort {lc($CompatProblems{$a}{"Withdrawn_Interface"}{"SharedLibrary"}{"Signature"}) cmp lc($CompatProblems{$b}{"Withdrawn_Interface"}{"SharedLibrary"}{"Signature"})} keys(%{$FuncWithdrawnFromHeaderLib{$HeaderName}{$SoName}})) - { - $Withdrawn_Number += 1; - my $SubReport = ""; - my $Signature = $CompatProblems{$Interface}{"Withdrawn_Interface"}{"SharedLibrary"}{"Signature"}; - if($Interface =~ /\A_Z/) - { - if($Signature) - { - $SubReport = insertIDs($ContentSpanStart.highLight_Signature_Italic_Color(htmlSpecChars($Signature)).$ContentSpanEnd."
\n".$ContentDivStart."[ symbol: $Interface ]

".$ContentDivEnd."\n"); - } - else - { - $SubReport = "".$Interface.""."
\n"; - } - } - else - { - if($Signature) - { - $SubReport = "".highLight_Signature_Italic_Color($Signature).""."
\n"; - } - else - { - $SubReport = "".$Interface.""."
\n"; - } - } - $WITHDRAWN_INTERFACES .= $SubReport; - } - $WITHDRAWN_INTERFACES .= "
\n"; - } - } - if($WITHDRAWN_INTERFACES) - { - $WITHDRAWN_INTERFACES = "

Withdrawn Interfaces ($Withdrawn_Number)


\n"."\n".$WITHDRAWN_INTERFACES."\n"."to the top
\n"; - } - return $WITHDRAWN_INTERFACES; -} - -sub get_Report_InterfaceProblems($) -{ - my $TargetPriority = $_[0]; - my ($INTERFACE_PROBLEMS, %FuncHeaderLib); - foreach my $Interface (sort keys(%CompatProblems)) - { - foreach my $Kind (sort keys(%{$CompatProblems{$Interface}})) - { - if($InterfaceProblems_Kind{$Kind} and ($Kind ne "Added_Interface") and ($Kind ne "Withdrawn_Interface")) - { - foreach my $Location (sort keys(%{$CompatProblems{$Interface}{$Kind}})) - { - my $SoName = $CompatProblems{$Interface}{$Kind}{$Location}{"Old_SoName"}; - my $HeaderName = $CompatProblems{$Interface}{$Kind}{$Location}{"Header"}; - $FuncHeaderLib{$HeaderName}{$SoName}{$Interface} = 1; - last; - } - } - } - } - my $Problems_Number = 0; - #interface problems - foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%FuncHeaderLib)) - { - foreach my $SoName (sort {lc($a) cmp lc($b)} keys(%{$FuncHeaderLib{$HeaderName}})) - { - my $HEADER_LIB_REPORT = ""; - foreach my $Interface (sort {lc($tr_name{$a}) cmp lc($tr_name{$b})} keys(%{$FuncHeaderLib{$HeaderName}{$SoName}})) - { - my $Signature = ""; - my $InterfaceProblemsReport = ""; - my $ProblemNum = 1; - foreach my $Kind (keys(%{$CompatProblems{$Interface}})) - { - foreach my $Location (keys(%{$CompatProblems{$Interface}{$Kind}})) - { - my $Incompatibility = ""; - my $Effect = ""; - my $Old_Value = htmlSpecChars($CompatProblems{$Interface}{$Kind}{$Location}{"Old_Value"}); - my $New_Value = htmlSpecChars($CompatProblems{$Interface}{$Kind}{$Location}{"New_Value"}); - my $Priority = $CompatProblems{$Interface}{$Kind}{$Location}{"Priority"}; - my $Target = $CompatProblems{$Interface}{$Kind}{$Location}{"Target"}; - my $Old_Size = $CompatProblems{$Interface}{$Kind}{$Location}{"Old_Size"}; - my $New_Size = $CompatProblems{$Interface}{$Kind}{$Location}{"New_Size"}; - my $InitialType_Type = $CompatProblems{$Interface}{$Kind}{$Location}{"InitialType_Type"}; - my $Parameter_Position = $CompatProblems{$Interface}{$Kind}{$Location}{"Parameter_Position"}; - my $Parameter_Position_Str = num_to_str($Parameter_Position + 1); - $Signature = $CompatProblems{$Interface}{$Kind}{$Location}{"Signature"} if(not $Signature); - next if($Priority ne $TargetPriority); - if($Kind eq "Function_Become_Static") - { - $Incompatibility = "Function become static.\n"; - $Effect = "Layout of parameter's stack has been changed and therefore parameters in higher positions in the stack may be incorrectly initialized by applications."; - } - elsif($Kind eq "Function_Become_NonStatic") - { - $Incompatibility = "Function become non-static.\n"; - $Effect = "Layout of parameter's stack has been changed and therefore parameters in higher positions in the stack may be incorrectly initialized by applications."; - } - elsif($Kind eq "Parameter_Type_And_Size") - { - $Incompatibility = "Type of $Parameter_Position_Str parameter $Target has been changed from $Old_Value ($Old_Size bytes) to $New_Value ($New_Size bytes).\n"; - $Effect = "Layout of parameter's stack has been changed and therefore parameters in higher positions in the stack may be incorrectly initialized by applications."; - } - elsif($Kind eq "Parameter_Type") - { - $Incompatibility = "Type of $Parameter_Position_Str parameter $Target has been changed from $Old_Value to $New_Value.\n"; - $Effect = "Replacement of parameter data type may indicate a change in the semantic meaning of this parameter."; - } - elsif($Kind eq "Withdrawn_Parameter") - { - $Incompatibility = "$Parameter_Position_Str parameter $Target has been withdrawn from the interface signature.\n"; - $Effect = "This parameter will be ignored by the interface."; - } - elsif($Kind eq "Added_Parameter") - { - $Incompatibility = "$Parameter_Position_Str parameter $Target has been added to the interface signature.\n"; - $Effect = "This parameter will not be initialized by applications."; - } - elsif($Kind eq "Parameter_BaseType_And_Size") - { - if($InitialType_Type eq "Pointer") - { - $Incompatibility = "Base type of $Parameter_Position_Str parameter $Target (pointer) has been changed from $Old_Value ($Old_Size bytes) to $New_Value ($New_Size bytes).\n"; - $Effect = "Memory stored by pointer may be incorrectly initialized by applications."; - } - else - { - $Incompatibility = "Base type of $Parameter_Position_Str parameter $Target has been changed from $Old_Value ($Old_Size bytes) to $New_Value ($New_Size bytes).\n"; - $Effect = "Layout of parameter's stack has been changed and therefore parameters in higher positions in the stack may be incorrectly initialized by applications."; - } - } - elsif($Kind eq "Parameter_BaseType") - { - if($InitialType_Type eq "Pointer") - { - $Incompatibility = "Base type of $Parameter_Position_Str parameter $Target (pointer) has been changed from $Old_Value to $New_Value.\n"; - $Effect = "Memory stored by pointer may be incorrectly initialized by applications."; - } - else - { - $Incompatibility = "Base type of $Parameter_Position_Str parameter $Target has been changed from $Old_Value to $New_Value.\n"; - $Effect = "Replacement of parameter base type may indicate a change in the semantic meaning of this parameter."; - } - } - elsif($Kind eq "Parameter_PointerLevel") - { - $Incompatibility = "Type pointer level of $Parameter_Position_Str parameter $Target has been changed from $Old_Value to $New_Value.\n"; - $Effect = "Possible incorrect initialization of $Parameter_Position_Str parameter $Target by applications."; - } - elsif($Kind eq "Return_Type_And_Size") - { - $Incompatibility = "Type of return value has been changed from $Old_Value ($Old_Size bytes) to $New_Value ($New_Size bytes).\n"; - $Effect = "Applications will get a different return value and execution may change."; - } - elsif($Kind eq "Return_Type") - { - $Incompatibility = "Type of return value has been changed from $Old_Value to $New_Value.\n"; - $Effect = "Replacement of return type may indicate a change in its semantic meaning."; - } - elsif($Kind eq "Return_BaseType_And_Size") - { - $Incompatibility = "Base type of return value has been changed from $Old_Value ($Old_Size bytes) to $New_Value ($New_Size bytes).\n"; - $Effect = "Applications will get a different return value and execution may change."; - } - elsif($Kind eq "Return_BaseType") - { - $Incompatibility = "Base type of return value has been changed from $Old_Value to $New_Value.\n"; - $Effect = "Replacement of return base type may indicate a change in its semantic meaning."; - } - elsif($Kind eq "Return_PointerLevel") - { - $Incompatibility = "Type pointer level of return value has been changed from $Old_Value to $New_Value.\n"; - $Effect = "Applications will get a different return value and execution may change."; - } - if($Incompatibility) - { - $InterfaceProblemsReport .= "$ProblemNum".$Incompatibility."".$Effect."\n"; - $ProblemNum += 1; - $Problems_Number += 1; - } - } - } - $ProblemNum -= 1; - if($InterfaceProblemsReport) - { - if($Interface =~ /\A_Z/) - { - if($Signature) - { - $HEADER_LIB_REPORT .= $ContentSpanStart."[+] ".highLight_Signature_Italic_Color(htmlSpecChars($Signature))." ($ProblemNum)".$ContentSpanEnd."
\n$ContentDivStart[ symbol: $Interface ]
\n"; - } - else - { - $HEADER_LIB_REPORT .= $ContentSpanStart."[+] ".$Interface." ($ProblemNum)".$ContentSpanEnd."
\n$ContentDivStart\n"; - } - } - else - { - if($Signature) - { - $HEADER_LIB_REPORT .= $ContentSpanStart."[+] ".highLight_Signature_Italic_Color(htmlSpecChars($Signature))." ($ProblemNum)".$ContentSpanEnd."
\n$ContentDivStart\n"; - } - else - { - $HEADER_LIB_REPORT .= $ContentSpanStart."[+] ".$Interface." ($ProblemNum)".$ContentSpanEnd."
\n$ContentDivStart\n"; - } - } - $HEADER_LIB_REPORT .= "$InterfaceProblemsReport
IncompatibilityEffect

$ContentDivEnd\n"; - $HEADER_LIB_REPORT = insertIDs($HEADER_LIB_REPORT); - } - } - if($HEADER_LIB_REPORT) - { - $INTERFACE_PROBLEMS .= "$HeaderName, $SoName
\n".$HEADER_LIB_REPORT."
"; - } - } - } - if($INTERFACE_PROBLEMS) - { - $INTERFACE_PROBLEMS = "\n

Interface problems, $TargetPriority risk ($Problems_Number)


\n"."\n".$INTERFACE_PROBLEMS."\n"."to the top
\n"; - } - return $INTERFACE_PROBLEMS; -} - -sub get_Report_TypeProblems($) -{ - my $TargetPriority = $_[0]; - my ($TYPE_PROBLEMS, %TypeHeader, %TypeChanges, %Type_MaxPriority) = (); - foreach my $Interface (sort keys(%CompatProblems)) - { - foreach my $Kind (keys(%{$CompatProblems{$Interface}})) - { - if($TypeProblems_Kind{$Kind}) - { - foreach my $Location (keys(%{$CompatProblems{$Interface}{$Kind}})) - { - my $Type_Name = $CompatProblems{$Interface}{$Kind}{$Location}{"Type_Name"}; - my $Priority = $CompatProblems{$Interface}{$Kind}{$Location}{"Priority"}; - my $Type_Header = $CompatProblems{$Interface}{$Kind}{$Location}{"Header"}; - %{$TypeChanges{$Type_Name}{$Kind}{$Location}} = %{$CompatProblems{$Interface}{$Kind}{$Location}}; - $TypeHeader{$Type_Header}{$Type_Name} = 1; - $Type_MaxPriority{$Type_Name}{$Kind} = max_priority($Type_MaxPriority{$Type_Name}{$Kind}, $Priority); - } - } - } - } - foreach my $Type_Name (keys(%TypeChanges)) - { - foreach my $Kind (keys(%{$TypeChanges{$Type_Name}})) - { - foreach my $Location (keys(%{$TypeChanges{$Type_Name}{$Kind}})) - { - my $Priority = $TypeChanges{$Type_Name}{$Kind}{$Location}{"Priority"}; - if(cmp_priority($Type_MaxPriority{$Type_Name}{$Kind}, $Priority)) - { - delete($TypeChanges{$Type_Name}{$Kind}{$Location}); - } - } - } - } - my $Problems_Number = 0; - foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%TypeHeader)) - { - my $HEADER_REPORT = ""; - foreach my $TypeName (sort {lc($a) cmp lc($b)} keys(%{$TypeHeader{$HeaderName}})) - { - my $ProblemNum = 1; - my $TypeProblemsReport = ""; - my %Kinds_Locations = (); - my %Kinds_Target = (); - foreach my $Kind (keys(%{$TypeChanges{$TypeName}})) - { - foreach my $Location (keys(%{$TypeChanges{$TypeName}{$Kind}})) - { - my $Priority = $TypeChanges{$TypeName}{$Kind}{$Location}{"Priority"}; - next if($Priority ne $TargetPriority); - $Kinds_Locations{$Kind}{$Location} = 1; - my $Incompatibility = ""; - my $Effect = ""; - my $Target = $TypeChanges{$TypeName}{$Kind}{$Location}{"Target"}; - next if($Kinds_Target{$Kind}{$Target}); - $Kinds_Target{$Kind}{$Target} = 1; - my $Old_Value = htmlSpecChars($TypeChanges{$TypeName}{$Kind}{$Location}{"Old_Value"}); - my $New_Value = htmlSpecChars($TypeChanges{$TypeName}{$Kind}{$Location}{"New_Value"}); - my $Old_Size = $TypeChanges{$TypeName}{$Kind}{$Location}{"Old_Size"}; - my $New_Size = $TypeChanges{$TypeName}{$Kind}{$Location}{"New_Size"}; - my $Type_Type = $TypeChanges{$TypeName}{$Kind}{$Location}{"Type_Type"}; - my $InitialType_Type = $TypeChanges{$TypeName}{$Kind}{$Location}{"InitialType_Type"}; - - if($Kind eq "Added_Virtual_Function") - { - $Incompatibility = "Virtual method "."".highLight_Signature(htmlSpecChars($Target)).""." has been added to this class and therefore the layout of virtual table has been changed."; - $Effect = "Call of any virtual method in this class or its subclasses will result in crash of application."; - } - elsif($Kind eq "Withdrawn_Virtual_Function") - { - $Incompatibility = "Virtual method "."".highLight_Signature(htmlSpecChars($Target)).""." has been withdrawn from this class and therefore the layout of virtual table has been changed."; - $Effect = "Call of any virtual method in this class or its subclasses will result in crash of application."; - } - elsif($Kind eq "Virtual_Function_Position") - { - $Incompatibility = "The relative position of virtual method "."".highLight_Signature(htmlSpecChars($Target)).""." has been changed from $Old_Value to $New_Value and therefore the layout of virtual table has been changed."; - $Effect = "Call of this virtual method will result in crash of application."; - } - elsif($Kind eq "Virtual_Function_Redefinition") - { - $Incompatibility = "Virtual method "."".highLight_Signature(htmlSpecChars($Old_Value)).""." has been redefined by "."".highLight_Signature(htmlSpecChars($New_Value)).""; - $Effect = "Method ".highLight_Signature(htmlSpecChars($New_Value))." will be called instead of ".highLight_Signature(htmlSpecChars($Old_Value)).""; - } - elsif($Kind eq "Virtual_Function_Redefinition_B") - { - $Incompatibility = "Virtual method "."".highLight_Signature(htmlSpecChars($New_Value)).""." has been redefined by "."".highLight_Signature(htmlSpecChars($Old_Value)).""; - $Effect = "Method ".highLight_Signature(htmlSpecChars($Old_Value))." will be called instead of ".highLight_Signature(htmlSpecChars($New_Value)).""; - } - elsif($Kind eq "Size") - { - $Incompatibility = "Size of this type has been changed from $Old_Value to $New_Value bytes."; - $Effect = "Change of type size may lead to different effects in different contexts. $ContentSpanStart"."[+] ..."."$ContentSpanEnd "; - } - elsif($Kind eq "BaseType") - { - $Incompatibility = "Base of this type has been changed from $Old_Value to $New_Value."; - $Effect = "Possible incorrect initialization of interface parameters by applications."; - } - elsif($Kind eq "Added_Member_And_Size") - { - $Incompatibility = "Member $Target has been added to this type."; - $Effect = "The size of the inclusive type has been changed."; - } - elsif($Kind eq "Added_Middle_Member_And_Size") - { - $Incompatibility = "Member $Target has been added between the first member and the last member of this structural type."; - $Effect = "1) Layout of structure members has been changed and therefore members in higher positions in the structure definition may be incorrectly accessed by applications.
2) The size of the inclusive type will also be affected."; - } - elsif($Kind eq "Member_Rename") - { - $Incompatibility = "Member $Target has been renamed to $New_Value."; - $Effect = "Renaming of a member in a structural data type may indicate a change in the semantic meaning of the member."; - } - elsif($Kind eq "Withdrawn_Member_And_Size") - { - $Incompatibility = "Member $Target has been withdrawn from this type."; - $Effect = "1) Applications will access incorrect memory when attempting to access this member.
2) The size of the inclusive type will also be affected."; - } - elsif($Kind eq "Withdrawn_Member") - { - $Incompatibility = "Member $Target has been withdrawn from this type."; - $Effect = "Applications will access incorrect memory when attempting to access this member."; - } - elsif($Kind eq "Withdrawn_Middle_Member_And_Size") - { - $Incompatibility = "Member $Target has been withdrawn from this structural type between the first member and the last member."; - $Effect = "1) Layout of structure members has been changed and therefore members in higher positions in the structure definition may be incorrectly accessed by applications.
2) Previous accesses of applications to the withdrawn member will be incorrect."; - } - elsif($Kind eq "Withdrawn_Middle_Member") - { - $Incompatibility = "Member $Target has been withdrawn from this structural type between the first member and the last member."; - $Effect = "1) Layout of structure members has been changed and therefore members in higher positions in the structure definition may be incorrectly accessed by applications.
2) Applications will access incorrect memory when attempting to access this member."; - } - elsif($Kind eq "Enum_Member_Value") - { - $Incompatibility = "Value of member $Target has been changed from $Old_Value to $New_Value."; - $Effect = "Applications may execute another branch of library code."; - } - elsif($Kind eq "Enum_Member_Name") - { - $Incompatibility = "Name of member with value $Target has been changed from $Old_Value to $New_Value."; - $Effect = "Applications may execute another branch of library code."; - } - elsif($Kind eq "Member_Type_And_Size") - { - $Incompatibility = "Type of member $Target has been changed from $Old_Value ($Old_Size bytes) to $New_Value ($New_Size bytes)."; - $Effect = "Layout of structure members has been changed and therefore members in higher positions in the structure definition may be incorrectly accessed by applications."; - } - elsif($Kind eq "Member_Type") - { - $Incompatibility = "Type of member $Target has been changed from $Old_Value to $New_Value."; - $Effect = "Replacement of the member data type may indicate a change in the semantic meaning of the member."; - } - elsif($Kind eq "Member_BaseType_And_Size") - { - if($InitialType_Type eq "Pointer") - { - $Incompatibility = "Base type of member $Target (pointer) has been changed from $Old_Value ($Old_Size bytes) to $New_Value ($New_Size bytes)."; - $Effect = "Possible access of applications to incorrect memory via member pointer."; - } - else - { - $Incompatibility = "Base type of member $Target has been changed from $Old_Value ($Old_Size bytes) to $New_Value ($New_Size bytes)."; - $Effect = "Layout of structure members has been changed and therefore members in higher positions in structure definition may be incorrectly accessed by applications."; - } - } - elsif($Kind eq "Member_BaseType") - { - if($InitialType_Type eq "Pointer") - { - $Incompatibility = "Base type of member $Target (pointer) has been changed from $Old_Value to $New_Value."; - $Effect = "Possible access of applications to incorrect memory via member pointer."; - } - else - { - $Incompatibility = "Base type of member $Target has been changed from $Old_Value to $New_Value."; - $Effect = "Replacement of member base type may indicate a change in the semantic meaning of this member."; - } - } - elsif($Kind eq "Member_PointerLevel") - { - $Incompatibility = "Type pointer level of member $Target has been changed from $Old_Value to $New_Value."; - $Effect = "Possible incorrect initialization of member $Target by applications."; - } - if($Incompatibility) - { - $TypeProblemsReport .= "$ProblemNum".$Incompatibility."$Effect\n"; - $ProblemNum += 1; - $Problems_Number += 1; - $Kinds_Locations{$Kind}{$Location} = 1; - } - } - } - $ProblemNum -= 1; - if($TypeProblemsReport) - { - my ($Affected_Interfaces_Header, $Affected_Interfaces) = getAffectedInterfaces($TypeName, \%Kinds_Locations); - $HEADER_REPORT .= $ContentSpanStart."[+] ".htmlSpecChars($TypeName)." ($ProblemNum)".$ContentSpanEnd."
\n$ContentDivStart$TypeProblemsReport
IncompatibilityEffect
"."$Affected_Interfaces_Header$Affected_Interfaces

$ContentDivEnd\n"; - $HEADER_REPORT = insertIDs($HEADER_REPORT); - } - } - if($HEADER_REPORT) - { - $TYPE_PROBLEMS .= "$HeaderName
\n".$HEADER_REPORT."
"; - } - } - if($TYPE_PROBLEMS) - { - my $Notations = ""; - if($TYPE_PROBLEMS =~ /'RetVal|'Obj/) - { - my @Notations_Array = (); - if($TYPE_PROBLEMS =~ /'RetVal/) - { - @Notations_Array = (@Notations_Array, "RetVal - function's return value"); - } - if($TYPE_PROBLEMS =~ /'Obj/) - { - @Notations_Array = (@Notations_Array, "Obj - method's object (C++)"); - } - $Notations = "Shorthand notations: ".join("; ", @Notations_Array).".
\n"; - } - $TYPE_PROBLEMS = "\n

Problems in Data Types, $TargetPriority risk ($Problems_Number)


\n".$Notations."\n".$TYPE_PROBLEMS."\n"."to the top
\n"; - } - return $TYPE_PROBLEMS; -} - -my $ContentSpanStart_2 = "\n"; - -sub getAffectedInterfaces($$) -{ - my ($Target_TypeName, $Kinds_Locations) = @_; - my ($Affected_Interfaces_Header, $Affected_Interfaces, %FunctionNumber) = (); - foreach my $Interface (sort {lc($tr_name{$a}) cmp lc($tr_name{$b})} keys(%CompatProblems)) - { - next if(($Interface =~ /C2/) or ($Interface =~ /D2/) or ($Interface =~ /D0/)); - next if(keys(%FunctionNumber)>1000); - my $FunctionProblem = ""; - my $MinPath_Length = ""; - my $MaxPriority = 0; - my $Location_Last = ""; - foreach my $Kind (keys(%{$CompatProblems{$Interface}})) - { - foreach my $Location (keys(%{$CompatProblems{$Interface}{$Kind}})) - { - next if(not $Kinds_Locations->{$Kind}{$Location}); - my $Type_Name = $CompatProblems{$Interface}{$Kind}{$Location}{"Type_Name"}; - my $Signature = $CompatProblems{$Interface}{$Kind}{$Location}{"Signature"}; - my $Parameter_Position = $CompatProblems{$Interface}{$Kind}{$Location}{"Parameter_Position"}; - my $Priority = $CompatProblems{$Interface}{$Kind}{$Location}{"Priority"}; - if($Type_Name eq $Target_TypeName) - { - $FunctionNumber{$Interface} = 1; - my $Path_Length = 0; - while($Location =~ /\-\>/g){$Path_Length += 1;} - if(($MinPath_Length eq "") or ($Path_Length<$MinPath_Length and $Priority_Value{$Priority}>$MaxPriority) or (($Location_Last =~ /RetVal/ or $Location_Last =~ /Obj/) and $Location !~ /RetVal|Obj/ and $Location !~ /\-\>/) or ($Location_Last =~ /RetVal|Obj/ and $Location_Last =~ /\-\>/ and $Location !~ /RetVal|Obj/ and $Location =~ /\-\>/)) - { - $MinPath_Length = $Path_Length; - $MaxPriority = $Priority_Value{$Priority}; - $Location_Last = $Location; - my $Description = get_AffectDescription($Interface, $Kind, $Location); - $FunctionProblem = "".highLight_Signature_PPos_Italic(htmlSpecChars($Signature), $Parameter_Position, 1, 0).":
"."".addArrows($Description)."
 
\n"; - } - } - } - } - $Affected_Interfaces .= $FunctionProblem; - } - $Affected_Interfaces .= "and other...
" if(keys(%FunctionNumber)>5000); - if($Affected_Interfaces) - { - $Affected_Interfaces_Header = $ContentSpanStart_2."[+] affected interfaces (".keys(%FunctionNumber).")".$ContentSpanEnd; - $Affected_Interfaces = $ContentDivStart.$Affected_Interfaces.$ContentDivEnd; - } - return ($Affected_Interfaces_Header, $Affected_Interfaces); -} - -my %Kind_TypeStructureChanged=( - "Size"=>1, - "Added_Member_And_Size"=>1, - "Added_Middle_Member_And_Size"=>1, - "Member_Rename"=>1, - "Withdrawn_Member_And_Size"=>1, - "Withdrawn_Member"=>1, - "Withdrawn_Middle_Member_And_Size"=>1, - "Enum_Member_Value"=>1, - "Enum_Member_Name"=>1, - "Member_Type_And_Size"=>1, - "Member_Type"=>1, - "Member_BaseType_And_Size"=>1, - "Member_BaseType"=>1, - "Member_PointerLevel"=>1, - "BaseType"=>1 -); - -my %Kind_VirtualTableChanged=( - "Added_Virtual_Function"=>1, - "Withdrawn_Virtual_Function"=>1, - "Virtual_Function_Position"=>1, - "Virtual_Function_Redefinition"=>1, - "Virtual_Function_Redefinition_B"=>1 -); - -sub get_AffectDescription($$$) -{ - my ($Interface, $Kind, $Location) = @_; - my $Target = $CompatProblems{$Interface}{$Kind}{$Location}{"Target"}; - my $Old_Value = $CompatProblems{$Interface}{$Kind}{$Location}{"Old_Value"}; - my $New_Value = $CompatProblems{$Interface}{$Kind}{$Location}{"New_Value"}; - my $Type_Name = $CompatProblems{$Interface}{$Kind}{$Location}{"Type_Name"}; - my $Parameter_Position = $CompatProblems{$Interface}{$Kind}{$Location}{"Parameter_Position"}; - my $Parameter_Name = $CompatProblems{$Interface}{$Kind}{$Location}{"Parameter_Name"}; - my $Parameter_Type_Name = $CompatProblems{$Interface}{$Kind}{$Location}{"Parameter_Type_Name"}; - my $Member_Type_Name = $CompatProblems{$Interface}{$Kind}{$Location}{"Member_Type_Name"}; - my $Object_Type_Name = $CompatProblems{$Interface}{$Kind}{$Location}{"Object_Type_Name"}; - my $Return_Type_Name = $CompatProblems{$Interface}{$Kind}{$Location}{"Return_Type_Name"}; - my $Start_Type_Name = $CompatProblems{$Interface}{$Kind}{$Location}{"Start_Type_Name"}; - my $InitialType_Type = $CompatProblems{$Interface}{$Kind}{$Location}{"InitialType_Type"}; - my $Parameter_Position_Str = num_to_str($Parameter_Position + 1); - my @Sentence_Parts = (); - my $Location_To_Type = $Location; - $Location_To_Type =~ s/\-\>[^>]+?\Z//; - if($Kind_VirtualTableChanged{$Kind}) - { - if($Kind eq "Virtual_Function_Redefinition") - { - @Sentence_Parts = (@Sentence_Parts, "This method become virtual and will be called instead of redefined method '".highLight_Signature(htmlSpecChars($Old_Value))."'."); - } - elsif($Kind eq "Virtual_Function_Redefinition_B") - { - @Sentence_Parts = (@Sentence_Parts, "This method become non-virtual and redefined method '".highLight_Signature(htmlSpecChars($Old_Value))."' will be called instead of it."); - } - else - { - @Sentence_Parts = (@Sentence_Parts, "Call of this virtual method will result in crash of application because the layout of virtual table has been changed."); - } - } - elsif($Kind_TypeStructureChanged{$Kind}) - { - if($Location_To_Type =~ /RetVal/) - {#return value - if($Location_To_Type =~ /\-\>/) - { - @Sentence_Parts = (@Sentence_Parts, "Member \'$Location_To_Type\' in return value"); - } - else - { - @Sentence_Parts = (@Sentence_Parts, "Return value"); - } - } - elsif($Location_To_Type =~ /Obj/) - {#object - if($Location_To_Type =~ /\-\>/) - { - @Sentence_Parts = (@Sentence_Parts, "Member \'$Location_To_Type\' in the object of this method"); - } - else - { - @Sentence_Parts = (@Sentence_Parts, "Object"); - } - } - else - {#parameters - if($Location_To_Type =~ /\-\>/) - { - @Sentence_Parts = (@Sentence_Parts, "Member \'$Location_To_Type\' of $Parameter_Position_Str parameter"); - } - else - { - @Sentence_Parts = (@Sentence_Parts, "$Parameter_Position_Str parameter"); - } - if($Parameter_Name) - { - @Sentence_Parts = (@Sentence_Parts, "\'$Parameter_Name\'"); - } - if($InitialType_Type eq "Pointer") - { - @Sentence_Parts = (@Sentence_Parts, "(pointer)"); - } - } - if($Start_Type_Name eq $Type_Name) - { - @Sentence_Parts = (@Sentence_Parts, "has type \'$Type_Name\'."); - } - else - { - @Sentence_Parts = (@Sentence_Parts, "has base type \'$Type_Name\'."); - } - } - return join(" ", @Sentence_Parts); -} - -sub create_HtmlReport() -{ - my $CssStyles = ""; - - my $JScripts = ""; - - writeFile("$REPORT_PATH/abi_compat_report.html", "\n\n\n - ABI compliance report for the library $TargetLibraryName from version ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." on ".getArch()."\n\n\n".$CssStyles."\n\n"."\n".$JScripts."\n\n\n\n
\n".get_Report_Header()."
\n".get_Summary()."
\n".get_Report_Added().get_Report_Withdrawn().get_Report_TypeProblems("High").get_Report_TypeProblems("Medium").get_Report_TypeProblems("Low").get_Report_InterfaceProblems("High").get_Report_InterfaceProblems("Medium").get_Report_InterfaceProblems("Low").get_Report_ChangedConstants().get_SourceInfo()."
\n"."



Generated on ".(localtime time)." for $TargetLibraryName by ABI-compliance-checker $ABI_COMPLIANCE_CHECKER_VERSION  
\n
\n"); -} - -sub trivialCmp($$) -{ - if(int($_[0]) > int($_[1])) - { - return 1; - } - elsif($_[0] eq $_[1]) - { - return 0; - } - else - { - return -1; - } -} - -sub addArrows($) -{ - my $Text = $_[0]; - #$Text =~ s/\-\>/→/g; - $Text =~ s/\-\>/−>/g; - return $Text; -} - -sub insertIDs($) -{ - my $Text = $_[0]; - while($Text =~ /CONTENT_ID/) - { - if(int($Content_Counter)%2) - { - $ContentID -= 1; - } - $Text =~ s/CONTENT_ID/c_$ContentID/; - $ContentID += 1; - $Content_Counter += 1; - } - return $Text; -} - -sub restrict_num_decimal_digits -{ - my $num=shift; - my $digs_to_cut=shift; - - if ($num=~/\d+\.(\d){$digs_to_cut,}/) - { - $num=sprintf("%.".($digs_to_cut-1)."f", $num); - } - return $num; -} - -sub parse_constants() -{ - my $CurHeader = ""; - foreach my $String (split("\n", $ConstantsSrc{$Version})) - {#detecting public and private constants using sources - if($String=~/#[ \t]+\d+[ \t]+\"(.+)\"/) - { - $CurHeader=$1; - } - if($String=~/\#[ \t]*define[ \t]+([_A-Z]+)[ \t]+(.*)[ \t]*\Z/) - { - my ($Name, $Value) = ($1, $2); - if(not $Constants{$Version}{$Name}{"Access"}) - { - $Constants{$Version}{$Name}{"Access"} = "public"; - $Constants{$Version}{$Name}{"Value"} = $Value; - $Constants{$Version}{$Name}{"Header"} = get_FileName($CurHeader); - } - } - elsif($String=~/\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) - { - my $Name = $1; - $Constants{$Version}{$Name}{"Access"} = "private"; - } - } - foreach my $Constant (keys(%{$Constants{$Version}})) - { - if(($Constants{$Version}{$Constant}{"Access"} eq "private") or not $Constants{$Version}{$Constant}{"Value"} - or $Constant=~/_h\Z/i) - { - delete($Constants{$Version}{$Constant}); - } - else - { - delete($Constants{$Version}{$Constant}{"Access"}); - } - } -} - -sub mergeConstants() -{ - return if(defined $AppPath); - foreach my $Constant (keys(%{$Constants{1}})) - { - my $Old_Value = $Constants{1}{$Constant}{"Value"}; - my $New_Value = $Constants{2}{$Constant}{"Value"}; - my $Header = $Constants{1}{$Constant}{"Header"}; - if($New_Value and $Old_Value and ($New_Value ne $Old_Value)) - { - %{$ConstantProblems{$Constant}} = ( - "Old_Value"=>$Old_Value, - "New_Value"=>$New_Value, - "Header"=>$Header - ); - } - } -} - -sub mergeHeaders_Separately() -{ - system("mkdir", "-p", "header_compile_errors/".$TargetLibraryName); - system("rm", "-fr", $ERR_PATH{1}, $ERR_PATH{2}); - my ($Header_Num, $Prev_Header_Length) = (0, 0); - my $All_Count = keys(%{$Headers{1}}); - foreach my $Header_Dest (sort {int($Headers{1}{$a}{"Position"})<=>int($Headers{1}{$b}{"Position"})} keys(%{$Headers{1}})) - { - my $Header_Name = $Headers{1}{$Header_Dest}{"Name"}; - my $Dest_Count = keys(%{$HeaderName_Destinations{1}{$Header_Name}}); - my $Identity = $Headers{1}{$Header_Dest}{"Identity"}; - my $Dest_Comment = ($Dest_Count>1 and $Identity=~/\//)?" ($Identity)":""; - print get_one_step_title($Header_Name.$Dest_Comment, $Header_Num, $All_Count, $Prev_Header_Length, 1)."\r"; - %TypeDescr = (); - %FuncDescr = (); - %ClassFunc = (); - %ClassVirtFunc = (); - %LibInfo = (); - %CompleteSignature = (); - %Cache = (); - $Version = 1; - parseHeader($Header_Dest); - $Version = 2; - my $PairHeaderDest = find_pair_header($Header_Dest); - if(not $PairHeaderDest) - { - $Header_Num += 1; - next; - } - parseHeader($PairHeaderDest); - mergeSignatures(); - mergeConstants(); - $Header_Num += 1; - $Prev_Header_Length = length($Header_Name.$Dest_Comment); - } - print get_one_step_title("", $All_Count, $All_Count, $Prev_Header_Length, 0)."\n"; -} - -sub get_one_step_title($$$$$) -{ - my ($Header_Name, $Num, $All_Count, $SpacesAtTheEnd, $ShowCurrent) = @_; - my ($Spaces_1, $Spaces_2, $Title) = (); - my $Title_1 = "checking headers: $Num/$All_Count [".restrict_num_decimal_digits($Num*100/$All_Count, 3)."%]".(($ShowCurrent)?",":""); - foreach (0 .. length("checking headers: ")+length($All_Count)*2+11 - length($Title_1)) - { - $Spaces_1 .= " "; - } - $Title .= $Title_1.$Spaces_1; - if($ShowCurrent) - { - my $Title_2 = "current: $Header_Name"; - foreach (0 .. $SpacesAtTheEnd - length($Header_Name)-1) - { - $Spaces_2 .= " "; - } - $Title .= $Title_2.$Spaces_2; - } - else - { - foreach (0 .. $SpacesAtTheEnd + length(" current: ") - 1) - { - $Title .= " "; - } - } - return $Title."\r"; -} - -sub find_pair_header($) -{ - my $Header_Dest = $_[0]; - my $Header_Name = $Headers{1}{$Header_Dest}{"Name"}; - my $Identity = $Headers{1}{$Header_Dest}{"Identity"}; - my @Pair_Dest = keys(%{$HeaderName_Destinations{2}{$Header_Name}}); - if($#Pair_Dest==0) - { - return $Pair_Dest[0]; - } - elsif($#Pair_Dest==-1) - { - return ""; - } - else - { - foreach my $Pair_Dest (@Pair_Dest) - { - my $Pair_Identity = $Headers{2}{$Pair_Dest}{"Identity"}; - if($Identity eq $Pair_Identity) - { - return $Pair_Dest; - } - } - return ""; - } -} - -sub getSymbols($) -{ - my $LibVersion = $_[0]; - my @SoLibPaths = getSoPaths($LibVersion); - if($#SoLibPaths eq -1 and not $CheckHeadersOnly) - { - print "ERROR: shared objects were not found\n"; - exit(1); - } - foreach my $SoLibPath (@SoLibPaths) - { - getSymbols_Lib($LibVersion, $SoLibPath, 0); - } -} - -sub separatePath($) -{ - return ("", $_[0])if($_[0] !~ /\//); - if($_[0] =~ /\A(.*\/)([^\/]*)\Z/) - { - return ($1, $2); - } - else - { - return ("", $_[0]); - } -} - -sub translateSymbols($) -{ - my $LibVersion = $_[0]; - my (@MnglNames, @UnMnglNames) = (); - foreach my $Interface (sort keys(%{$Interface_Library{$LibVersion}})) - { - if($Interface =~ /\A_Z/) - { - $Interface =~ s/[\@]+(.*)\Z//; - push(@MnglNames, $Interface); - } - else - { - $tr_name{$Interface} = $Interface; - $mangled_name{$tr_name{$Interface}} = $Interface; - } - } - if($#MnglNames > -1) - { - @UnMnglNames = reverse(unmangleArray(@MnglNames)); - foreach my $Interface (sort keys(%{$Interface_Library{$LibVersion}})) - { - if($Interface =~ /\A_Z/) - { - $Interface =~ s/[\@]+(.*)\Z//; - $tr_name{$Interface} = pop(@UnMnglNames); - $mangled_name{correctName($tr_name{$Interface})} = $Interface; - } - } - } -} - -sub detectAdded() -{ - #detecting added - foreach my $Interface (keys(%{$Interface_Library{2}})) - { - if(not $Interface_Library{1}{$Interface}) - { - $AddedInt{$Interface} = 1; - my ($MnglName, $SymbolVersion) = ($Interface, ""); - if($Interface =~ /\A(.+)[\@]+(.+)\Z/) - { - ($MnglName, $SymbolVersion) = ($1, $2); - } - $FuncAttr{2}{$Interface}{"Signature"} = $tr_name{$MnglName}.(($SymbolVersion)?"\@".$SymbolVersion:""); - } - } -} - -sub detectWithdrawn() -{ - #detecting withdrawn - foreach my $Interface (keys(%{$Interface_Library{1}})) - { - if(not $Interface_Library{2}{$Interface} and not $Interface_Library{2}{$SymVer{2}{$Interface}}) - { - next if($DepInterfaces{2}{$Interface}); - $WithdrawnInt{$Interface} = 1; - my ($MnglName, $SymbolVersion) = ($Interface, ""); - if($Interface =~ /\A(.+)[\@]+(.+)\Z/) - { - ($MnglName, $SymbolVersion) = ($1, $2); - } - $FuncAttr{1}{$Interface}{"Signature"} = $tr_name{$MnglName}.(($SymbolVersion)?"\@".$SymbolVersion:""); - } - } -} - -sub isRecurLib($) -{ - my $LibName = $_[0]; - foreach my $LibNameInStack (@RecurLib) - { - if($LibName eq $LibNameInStack) - { - return 1; - } - } - return 0; -} - -sub getSymbols_App($) -{ - my $Path = $_[0]; - return () if(not $Path or not -f $Path); - my @Ints = (); - open(APP, "readelf -WhlSsdA $Path |"); - my $symtab=0;#indicates that we are processing 'symtab' section of 'readelf' output - while() - { - if($symtab == 1) { - #do nothing with symtab (but there are some plans for the future) - next; - } - if( /'.dynsym'/ ) { - $symtab=0; - } - elsif( /'.symtab'/ ) { - $symtab=1; - } - elsif(my ($fullname, $idx, $Ndx) = readlile_ELF($_)) { - if( $Ndx eq "UND" ) { - #only exported interfaces - push(@Ints, $fullname); - } - } - } - close(APP); - return @Ints; -} - -sub readlile_ELF($) -{ - if($_[0]=~/\s*\d+:\s+(\w*)\s+\w+\s+(\w+)\s+(\w+)\s+(\w+)\s+(\w+)\s((\w|@|\.)+)/) - {#the line of 'readelf' output corresponding to the interface - my ($value, $type, $bind, $vis, $Ndx, $fullname)=($1, $2, $3, $4, $5, $6); - if(($bind ne "WEAK") and ($bind ne "GLOBAL")) { - return (); - } - if(($type ne "FUNC") and ($type ne "OBJECT") and ($type ne "COMMON")) { - return (); - } - if($vis ne "DEFAULT") { - return (); - } - if(($Ndx eq "ABS") and ($value !~ /\D|1|2|3|4|5|6|7|8|9/)) { - return (); - } - return ($fullname, $value, $Ndx); - } - else - { - return (); - } -} - -sub getSymbols_Lib($$$) -{ - my ($LibVersion, $Lib_Path, $IsNeededLib) = @_; - return if(not $Lib_Path or not -f $Lib_Path); - my ($Lib_Dir, $Lib_SoName) = separatePath($Lib_Path); - return if($CheckedSoLib{$LibVersion}{$Lib_SoName} and $IsNeededLib); - return if(isRecurLib($Lib_SoName) or $#RecurLib>=1); - $CheckedSoLib{$LibVersion}{$Lib_SoName} = 1; - push(@RecurLib, $Lib_SoName); - my (%Value_Interface, %Interface_Value, %NeededLib) = (); - if(not $IsNeededLib) - { - $SoNames_All{$LibVersion}{$Lib_SoName} = 1; - } - open(SOLIB, "readelf -WhlSsdA $Lib_Path |"); - my $symtab=0;#indicates that we are processing 'symtab' section of 'readelf' output - while() - { - if($symtab == 1) { - #do nothing with symtab (but there are some plans for the future) - next; - } - if(/'.dynsym'/) { - $symtab=0; - } - elsif(/'.symtab'/) { - $symtab=1; - } - elsif(/NEEDED.+\[([^\[\]]+)\]/) - { - $NeededLib{$1} = 1; - } - elsif(my ($fullname, $idx, $Ndx) = readlile_ELF($_)) { - if( $Ndx eq "UND" ) { - #ignore interfaces that are exported form somewhere else - next; - } - my ($realname, $version) = ($fullname, ""); - if($fullname =~ /\A([^@]+)[\@]+([^@]+)\Z/) - { - ($realname, $version) = ($1, $2); - } - next if(defined $InterfacesListPath and not $InterfacesList{$realname}); - next if(defined $AppPath and not $InterfacesList_App{$realname}); - if($IsNeededLib) - { - $DepInterfaces{$LibVersion}{$fullname} = 1; - } - if(not $IsNeededLib or (defined $InterfacesListPath and $InterfacesList{$realname}) or (defined $AppPath and $InterfacesList_App{$realname})) - { - $Interface_Library{$LibVersion}{$fullname} = $Lib_SoName; - $Library_Interface{$LibVersion}{$Lib_SoName}{$fullname} = 1; - $Interface_Value{$LibVersion}{$fullname} = $idx; - $Value_Interface{$LibVersion}{$idx}{$fullname} = 1; - if(not $Language{$LibVersion}{$Lib_SoName}) - { - if($fullname =~ /\A_Z[A-Z]*[0-9]+/) - { - $Language{$LibVersion}{$Lib_SoName} = "C++"; - } - } - } - } - } - close(SOLIB); - if(not $IsNeededLib) - { - foreach my $Interface_Name (keys(%{$Interface_Library{$LibVersion}})) - { - next if($Interface_Name !~ /\@/); - my $Interface_SymName = ""; - foreach my $InterfaceName_SameValue (keys(%{$Value_Interface{$LibVersion}{$Interface_Value{$LibVersion}{$Interface_Name}}})) - { - if($InterfaceName_SameValue ne $Interface_Name) - { - $SymVer{$LibVersion}{$InterfaceName_SameValue} = $Interface_Name; - $Interface_SymName = $InterfaceName_SameValue; - last; - } - } - if(not $Interface_SymName) - { - if($Interface_Name =~ /\A([^@]*)[\@]+([^@]*)\Z/ and not $SymVer{$LibVersion}{$1}) - { - $SymVer{$LibVersion}{$1} = $Interface_Name; - } - } - } - } - foreach my $SoLib (keys(%NeededLib)) - { - getSymbols_Lib($LibVersion, find_solib_path($Lib_Dir, $SoLib), 1); - } - pop(@RecurLib); -} - -sub find_solib_path($$) -{ - my ($Dir, $SoName) = @_; - $Dir=~s/\/\Z//g; - if(-f $Dir."/".$SoName) - { - return $Dir."/".$SoName; - } - else - { - return $SoLib_DefaultPath{$SoName}; - } -} - -sub symbols_Preparation($) -{#recreate %SoNames and %Language using info from *.abi file - my $LibVersion = $_[0]; - foreach my $Lib_SoName (keys(%{$Library_Interface{$LibVersion}})) - { - foreach my $Interface_Name (keys(%{$Library_Interface{$LibVersion}{$Lib_SoName}})) - { - $Interface_Library{$LibVersion}{$Interface_Name} = $Lib_SoName; - $SoNames_All{$LibVersion}{$Lib_SoName} = 1; - if(not $Language{$LibVersion}{$Lib_SoName}) - { - if($Interface_Name =~ /\A_Z[A-Z]*[0-9]+/) - { - $Language{$LibVersion}{$Lib_SoName} = "C++"; - } - } - } - } -} - -sub getSoPaths($) -{ - my $LibVersion = $_[0]; - my @SoPaths = (); - foreach my $Dest (split("\n", $Descriptor{$LibVersion}{"Libs"})) - { - $Dest =~ s/\A\s+|\s+\Z//g; - next if(not $Dest); - if(not -e $Dest) - { - print "ERROR: can't access \'$Dest\'\n"; - } - my @SoPaths_Dest = getSOPaths_Dest($Dest); - foreach (@SoPaths_Dest) - { - push(@SoPaths, $_); - } - } - return @SoPaths; -} - -sub getSOPaths_Dest($) -{ - my $Dest = $_[0]; - if(-f $Dest) - { - return $Dest; - } - my @AllObjects = cmd_find($Dest,"f","*\.so*"); - my @SOPaths = (); - foreach my $SharedObject (@AllObjects) - { - if(cmd_file($SharedObject) =~ /shared object/) - { - @SOPaths = (@SOPaths, $SharedObject); - } - } - return @SOPaths; -} - -sub genDescriptorTemplate() -{ - writeFile("library-descriptor.xml", $Descriptor_Template."\n"); - print "descriptor template named 'library-descriptor.xml' has been generated in the current directory\n"; -} - -sub detectPointerSize() -{ - `mkdir -p temp`; - writeFile("temp/get_pointer_size.c", "#include -int main() -{ - printf(\"\%d\", sizeof(int*)); - return 0; -}\n"); - system("gcc temp/get_pointer_size.c -o temp/get_pointer_size"); - $POINTER_SIZE = `./temp/get_pointer_size`; - `rm -fr temp`; -} - -sub data_Preparation($) -{ - my $LibVersion = $_[0]; - if($Descriptor{$LibVersion}{"Path"} =~ /\.abi\.tar\.gz/) - { - my $FileName = cmd_tar($Descriptor{$LibVersion}{"Path"}); - if($FileName =~ /\.abi/) - { - chomp($FileName); - my $LibraryABI = eval readFile($FileName); - system("rm", "-f", $FileName); - $TypeDescr{$LibVersion} = $LibraryABI->{"TypeDescr"}; - $FuncDescr{$LibVersion} = $LibraryABI->{"FuncDescr"}; - $Library_Interface{$LibVersion} = $LibraryABI->{"Interfaces"}; - $SymVer{$LibVersion} = $LibraryABI->{"SymVer"}; - $Tid_TDid{$LibVersion} = $LibraryABI->{"Tid_TDid"}; - $Descriptor{$LibVersion}{"Version"} = $LibraryABI->{"LibraryVersion"}; - $OpaqueTypes{$LibVersion} = $LibraryABI->{"OpaqueTypes"}; - $InternalInterfaces{$LibVersion} = $LibraryABI->{"InternalInterfaces"}; - $Headers{$LibVersion} = $LibraryABI->{"Headers"}; - $SoNames_All{$LibVersion} = $LibraryABI->{"SharedObjects"}; - $Constants{$LibVersion} = $LibraryABI->{"Constants"}; - if($LibraryABI->{"ABI_COMPLIANCE_CHECKER_VERSION"} ne $ABI_COMPLIANCE_CHECKER_VERSION) - { - print "ERROR: incompatible version of specified ABI dump (allowed only $ABI_COMPLIANCE_CHECKER_VERSION)\n"; - exit(1); - } - foreach my $Destination (keys(%{$Headers{$LibVersion}})) - { - my $Header = get_FileName($Destination); - $HeaderName_Destinations{$LibVersion}{$Header}{$Destination} = 1; - } - symbols_Preparation($LibVersion); - } - } - elsif($Descriptor{$LibVersion}{"Path"} =~ /\.tar\.gz\Z/) - { - print "ERROR: descriptor must be an XML file or '*.abi.tar.gz' ABI dump\n"; - exit(1); - } - else - { - readDescriptor($LibVersion); - if(not $CheckHeadersOnly) - { - getSymbols($LibVersion); - } - headerSearch($LibVersion); - } -} - -sub dump_sorting($) -{ - my $hash = $_[0]; - if((keys(%{$hash}))[0] =~ /\A[0-9]+\Z/) - { - return [sort {int($a) <=> int($b)} keys %{$hash}]; - } - else - { - return [sort {$a cmp $b} keys %{$hash}]; - } -} - -sub get_solib_default_paths() -{ - foreach my $Line (split("\n", `ldconfig -p`)) - { - if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/) - { - $SoLib_DefaultPath{$1} = $2; - } - } -} - -sub scenario() -{ - if(defined $Help) - { - HELP_MESSAGE(); - exit(0); - } - if(defined $ShowVersion) - { - print "ABI Compliance Checker $ABI_COMPLIANCE_CHECKER_VERSION\nCopyright (C) The Linux Foundation\nCopyright (C) Institute for System Programming, RAS\nLicense GPLv2: GNU GPL version 2 \nThis program is free software: you can redistribute it and/or modify it.\n\nWritten by Andrey Ponomarenko.\n"; - exit(0); - } - $Data::Dumper::Sortkeys = \&dump_sorting; - if(defined $TestSystem) - { - testSystem_cpp(); - testSystem_c(); - exit(0); - } - if($GenerateDescriptor) - { - genDescriptorTemplate(); - exit(0); - } - if(not defined $TargetLibraryName) - { - print "select library name (option -l )\n"; - exit(1); - } - if(defined $InterfacesListPath) - { - if(not -f $InterfacesListPath) - { - print "ERROR: can't access file $InterfacesListPath\n"; - exit(1); - } - foreach my $Interface (split("\n", readFile($InterfacesListPath))) - { - $InterfacesList{$Interface} = 1; - } - } - if($AppPath) - { - if(-f $AppPath) - { - foreach my $Interface (getSymbols_App($AppPath)) - { - $InterfacesList_App{$Interface} = 1; - } - } - else - { - print "ERROR: can't access file \'$AppPath\'\n"; - exit(1); - } - } - get_solib_default_paths(); - if($DumpInfo_DescriptorPath) - { - if(not -f $DumpInfo_DescriptorPath) - { - print "ERROR: can't access file \'$DumpInfo_DescriptorPath\'\n"; - exit(1); - } - $Descriptor{1}{"Path"} = $DumpInfo_DescriptorPath; - readDescriptor(1); - detectPointerSize(); - getSymbols(1); - translateSymbols(1); - headerSearch(1); - parseHeaders_AllInOne(1); - cleanData(1); - my %LibraryABI = (); - print "creating library ABI info dump ...\n"; - $LibraryABI{"TypeDescr"} = $TypeDescr{1}; - $LibraryABI{"FuncDescr"} = $FuncDescr{1}; - $LibraryABI{"Interfaces"} = $Library_Interface{1}; - $LibraryABI{"SymVer"} = $SymVer{1}; - $LibraryABI{"LibraryVersion"} = $Descriptor{1}{"Version"}; - $LibraryABI{"Library"} = $TargetLibraryName; - $LibraryABI{"SharedObjects"} = $SoNames_All{1}; - $LibraryABI{"Tid_TDid"} = $Tid_TDid{1}; - $LibraryABI{"OpaqueTypes"} = $OpaqueTypes{1}; - $LibraryABI{"InternalInterfaces"} = $InternalInterfaces{1}; - $LibraryABI{"Headers"} = $Headers{1}; - $LibraryABI{"Constants"} = $Constants{1}; - $LibraryABI{"ABI_COMPLIANCE_CHECKER_VERSION"} = $ABI_COMPLIANCE_CHECKER_VERSION; - my $InfoDump_FilePath = "abi_dumps/$TargetLibraryName"; - my $InfoDump_FileName = $TargetLibraryName."_".$Descriptor{1}{"Version"}.".abi"; - system("mkdir", "-p", $InfoDump_FilePath); - system("rm", "-f", $InfoDump_FilePath."/".$InfoDump_FileName.".tar.gz"); - writeFile("$InfoDump_FilePath/$InfoDump_FileName", Dumper(\%LibraryABI)); - system("cd ".esc($InfoDump_FilePath)." && tar -cf ".esc($InfoDump_FileName).".tar ".esc($InfoDump_FileName)); - system("cd ".esc($InfoDump_FilePath)." && gzip ".esc($InfoDump_FileName).".tar --best"); - system("rm", "-f", $InfoDump_FilePath."/".$InfoDump_FileName); - if($?) - { - print "ERROR: can't create library ABI info dump\n"; - exit(1); - } - else - { - print "see library ABI info dump in \'$InfoDump_FilePath/$InfoDump_FileName\.tar\.gz\': use it instead of library version descriptor on other machine\n"; - exit(0); - } - } - if(not $Descriptor{1}{"Path"}) - { - print "select 1st library descriptor (option -d1 )\n"; - exit(1); - } - if(not -f $Descriptor{1}{"Path"}) - { - print "ERROR: descriptor d1 does not exist, incorrect file path '".$Descriptor{1}{"Path"}."'\n"; - exit(1); - } - if(not $Descriptor{2}{"Path"}) - { - print "select 2nd library descriptor (option -d2 )\n"; - exit(1); - } - if(not -f $Descriptor{2}{"Path"}) - { - print "ERROR: descriptor d2 does not exist, incorrect file path '".$Descriptor{2}{"Path"}."'\n"; - exit(1); - } - $StartTime = localtime time; - print "preparation...\n"; - data_Preparation(1); - data_Preparation(2); - if($AppPath and not keys(%{$Interface_Library{1}})) - { - print "WARNING: symbols from the specified application were not found in the specified library shared objects\n"; - } - $REPORT_PATH = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"}; - system("mkdir", "-p", $REPORT_PATH); - system("rm", "-f", $REPORT_PATH."/abi_compat_report.html"); - detectPointerSize(); - translateSymbols(1); - translateSymbols(2); - if(not $CheckHeadersOnly) - { - detectAdded(); - detectWithdrawn(); - } - #headers merging - if($HeaderCheckingMode_Separately and $Descriptor{1}{"Path"} !~ /\.abi\.tar\.gz/ and $Descriptor{2}{"Path"} !~ /\.abi\.tar\.gz/) - { - mergeHeaders_Separately(); - } - else - { - if($Descriptor{1}{"Path"} !~ /\.abi\.tar\.gz/) - { - parseHeaders_AllInOne(1); - } - if($Descriptor{2}{"Path"} !~ /\.abi\.tar\.gz/) - { - parseHeaders_AllInOne(2); - } - print "comparing headers ...\n"; - mergeSignatures(); - mergeConstants(); - } - #libraries merging - if(not $CheckHeadersOnly) - { - print "comparing shared objects ...\n"; - mergeLibs(); - } - print "creating ABI compliance report ...\n"; - create_HtmlReport(); - if($HeaderCheckingMode_Separately) - { - if(keys(%HeaderCompileError)) - { - print "\nWARNING: compilation errors in following headers:\n"; - foreach my $Header (keys(%HeaderCompileError)) - { - print $Header." "; - } - print "\nyou can see compilation errors in the following files:\n '$ERR_PATH{1}'\n '$ERR_PATH{2}'\n"; - } - } - `rm -fr temp`; - print "\nstarted: $StartTime, finished: ".(localtime time)."\n" if($ShowExpendTime); - print "see the ABI compliance report in the file '$REPORT_PATH/abi_compat_report.html'\n"; - exit(0); -} - -scenario(); diff --git a/abicheck/run_abi_test b/abicheck/run_abi_test index 4e4bdf298..668ce8e12 100755 --- a/abicheck/run_abi_test +++ b/abicheck/run_abi_test @@ -5,10 +5,15 @@ if [ ! -d ../build ]; then exit 1 fi +if [ ! -x $(which abi-complicance-checker > /dev/null 2>&1) ]; then + echo "Please install the 'abi-complicance-checker' package" + exit 1 +fi + LIBPATH=$(find /usr/lib/ -type f -name "libapt-*.so.*" -printf %p\\\\n) sed s#@installed_libapt@#$LIBPATH# apt_installed.xml.in > apt_installed.xml BUILDPATH=$(readlink -f ../build) sed s#@build_path@#$BUILDPATH# apt_build.xml.in > apt_build.xml -perl abi-compliance-checker.pl -l apt -d1 apt_installed.xml -d2 apt_build.xml +abi-compliance-checker -l apt -d1 apt_installed.xml -d2 apt_build.xml -- cgit v1.2.3 From 7dd5854b48f5d59c02fb0068d850384f3e678c67 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 12 Aug 2013 17:41:36 +0200 Subject: improve error message --- cmdline/apt-cdrom.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmdline/apt-cdrom.cc b/cmdline/apt-cdrom.cc index 545edf439..a95970782 100644 --- a/cmdline/apt-cdrom.cc +++ b/cmdline/apt-cdrom.cc @@ -67,7 +67,8 @@ void pkgCdromTextStatus::Prompt(const char *Text) char C; cout << Text << ' ' << flush; if (read(STDIN_FILENO,&C,1) < 0) - _error->Errno("pkgCdromTextStatus::Prompt", "failed to prompt"); + _error->Errno("pkgCdromTextStatus::Prompt", + "Failed to read from standard input (not a terminal?)"); if (C != '\n') cout << endl; } -- cgit v1.2.3 From 29a59c460403820d0f039398194e321b7e0921fc Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 9 Aug 2013 22:20:27 +0200 Subject: test Release file handling with expired keys Signing files with expired keys is not as easy as it sounds, so the framework jumps a few loops to do it, but it might come in handy to have an expired key around for later tests even if it is not that different from having no key in regards to APT behaviour. Git-Dch: Ignore --- test/integration/framework | 35 ++++++++++++++++++++----- test/integration/rexexpired.pub | Bin 0 -> 1200 bytes test/integration/rexexpired.sec | Bin 0 -> 2502 bytes test/integration/test-releasefile-verification | 35 +++++++++++++++++++++++-- 4 files changed, 62 insertions(+), 8 deletions(-) create mode 100644 test/integration/rexexpired.pub create mode 100644 test/integration/rexexpired.sec diff --git a/test/integration/framework b/test/integration/framework index 7dd7c20a7..f64b8482c 100644 --- a/test/integration/framework +++ b/test/integration/framework @@ -711,22 +711,45 @@ setupaptarchive() { signreleasefiles() { local SIGNER="${1:-Joe Sixpack}" + local GPG="gpg --batch --yes --no-default-keyring --trustdb-name rootdir/etc/apt/trustdb.gpg" msgninfo "\tSign archive with $SIGNER key… " - local SECKEYS="" + local REXKEY='keys/rexexpired' + local SECEXPIREBAK="${REXKEY}.sec.bak" + local PUBEXPIREBAK="${REXKEY}.pub.bak" + if [ "${SIGNER}" = 'Rex Expired' ]; then + # the key is expired, so gpg doesn't allow to sign with and the --faked-system-time + # option doesn't exist anymore (and using faketime would add a new obscure dependency) + # therefore we 'temporary' make the key not expired and restore a backup after signing + cp ${REXKEY}.sec $SECEXPIREBAK + cp ${REXKEY}.pub $PUBEXPIREBAK + local SECUNEXPIRED="${REXKEY}.sec.unexpired" + local PUBUNEXPIRED="${REXKEY}.pub.unexpired" + if [ -f "$SECUNEXPIRED" ] && [ -f "$PUBUNEXPIRED" ]; then + cp $SECUNEXPIRED ${REXKEY}.sec + cp $PUBUNEXPIRED ${REXKEY}.pub + else + printf "expire\n1w\nsave\n" | $GPG --keyring ${REXKEY}.pub --secret-keyring ${REXKEY}.sec --command-fd 0 --edit-key "${SIGNER}" >/dev/null 2>&1 || true + cp ${REXKEY}.sec $SECUNEXPIRED + cp ${REXKEY}.pub $PUBUNEXPIRED + fi + fi for KEY in $(find keys/ -name '*.sec'); do - SECKEYS="$SECKEYS --secret-keyring $KEY" + GPG="$GPG --secret-keyring $KEY" done - local PUBKEYS="" for KEY in $(find keys/ -name '*.pub'); do - PUBKEYS="$PUBKEYS --keyring $KEY" + GPG="$GPG --keyring $KEY" done for RELEASE in $(find aptarchive/ -name Release); do - gpg --yes --no-default-keyring $SECKEYS $PUBKEYS --default-key "$SIGNER" -abs -o ${RELEASE}.gpg ${RELEASE} + $GPG --default-key "$SIGNER" --armor --detach-sign --sign --output ${RELEASE}.gpg ${RELEASE} local INRELEASE="$(echo "${RELEASE}" | sed 's#/Release$#/InRelease#')" - gpg --yes --no-default-keyring $SECKEYS $PUBKEYS --default-key "$SIGNER" --clearsign -o $INRELEASE $RELEASE + $GPG --default-key "$SIGNER" --clearsign --output $INRELEASE $RELEASE # we might have set a specific date for the Release file, so copy it touch -d "$(stat --format "%y" ${RELEASE})" ${RELEASE}.gpg ${INRELEASE} done + if [ -f "$SECEXPIREBAK" ] && [ -f "$PUBEXPIREBAK" ]; then + mv -f $SECEXPIREBAK ${REXKEY}.sec + mv -f $PUBEXPIREBAK ${REXKEY}.pub + fi msgdone "info" } diff --git a/test/integration/rexexpired.pub b/test/integration/rexexpired.pub new file mode 100644 index 000000000..5ab2e489a Binary files /dev/null and b/test/integration/rexexpired.pub differ diff --git a/test/integration/rexexpired.sec b/test/integration/rexexpired.sec new file mode 100644 index 000000000..dc00168cd Binary files /dev/null and b/test/integration/rexexpired.sec differ diff --git a/test/integration/test-releasefile-verification b/test/integration/test-releasefile-verification index e56f458d3..daba3919b 100755 --- a/test/integration/test-releasefile-verification +++ b/test/integration/test-releasefile-verification @@ -107,13 +107,24 @@ runtest() { " aptcache show apt installaptnew + prepare ${PKGFILE} + rm -rf rootdir/var/lib/apt/lists + cp keys/rexexpired.pub rootdir/etc/apt/trusted.gpg.d/rexexpired.gpg + signreleasefiles 'Rex Expired' + find aptarchive/ -name "$DELETEFILE" -delete + msgtest 'Cold archive signed by' 'Rex Expired' + aptget update 2>&1 | grep -E '^W: .* KEYEXPIRED' > /dev/null && msgpass || msgfail + testequal "$(cat ${PKGFILE}) +" aptcache show apt + failaptold + rm rootdir/etc/apt/trusted.gpg.d/rexexpired.gpg prepare ${PKGFILE} rm -rf rootdir/var/lib/apt/lists signreleasefiles 'Marvin Paranoid' find aptarchive/ -name "$DELETEFILE" -delete msgtest 'Cold archive signed by' 'Marvin Paranoid' - aptget update 2>&1 | grep -E '^(W|E): ' > /dev/null && msgpass || msgfail + aptget update 2>&1 | grep -E '^W: .* NO_PUBKEY' > /dev/null && msgpass || msgfail testequal "$(cat ${PKGFILE}) " aptcache show apt failaptold @@ -147,10 +158,30 @@ runtest() { signreleasefiles 'Marvin Paranoid' find aptarchive/ -name "$DELETEFILE" -delete msgtest 'Good warm archive signed by' 'Marvin Paranoid' - aptget update 2>&1 | grep -E '^(W|E): ' > /dev/null && msgpass || msgfail + aptget update 2>&1 | grep -E '^W: .* NO_PUBKEY' > /dev/null && msgpass || msgfail + testequal "$(cat ${PKGFILE}) +" aptcache show apt + installaptold + + prepare ${PKGFILE}-new + cp keys/rexexpired.pub rootdir/etc/apt/trusted.gpg.d/rexexpired.gpg + signreleasefiles 'Rex Expired' + find aptarchive/ -name "$DELETEFILE" -delete + msgtest 'Good warm archive signed by' 'Rex Expired' + aptget update 2>&1 | grep -E '^W: .* KEYEXPIRED' > /dev/null && msgpass || msgfail testequal "$(cat ${PKGFILE}) " aptcache show apt installaptold + rm rootdir/etc/apt/trusted.gpg.d/rexexpired.gpg + + prepare ${PKGFILE}-new + signreleasefiles + find aptarchive/ -name "$DELETEFILE" -delete + msgtest 'Good warm archive signed by' 'Joe Sixpack' + aptget update 2>&1 | grep -E '^(W|E): ' > /dev/null && msgfail || msgpass + testequal "$(cat ${PKGFILE}-new) +" aptcache show apt + installaptnew } runtest2() { -- cgit v1.2.3 From 0440d936d70b1e331d49bbc32735f1b749632604 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 10 Aug 2013 10:01:06 +0200 Subject: add chronic-like testsuccess/testfailure helpers For many commands the output isn't stable (like then dpkg is called) but the exitcode is, so this helper enhances the common && msgpass || msgfail by generating automatically a msgtest and showing the output of the command in case of failure instead of discarding it unconditionally, the later being chronic-like behaviour Git-Dch: Ignore --- test/integration/framework | 34 ++++++++++++++++++++++ test/integration/test-apt-cdrom | 2 +- test/integration/test-apt-get-autoremove | 10 +++---- .../test-bug-407511-fail-invalid-default-release | 4 +-- test/integration/test-bug-602412-dequote-redirect | 4 +-- .../integration/test-bug-604222-new-and-autoremove | 2 +- .../test-bug-604401-files-are-directories | 10 +++---- test/integration/test-bug-611729-mark-as-manual | 20 ++++++------- .../test-bug-612099-multiarch-conflicts | 12 ++++---- test/integration/test-bug-612557-garbage-upgrade | 4 +-- .../test-bug-612958-use-dpkg-multiarch-config | 4 +-- .../test-bug-613420-new-garbage-dependency | 2 +- ...test-bug-64141-install-dependencies-for-on-hold | 2 +- .../test-bug-673536-pre-depends-breaks-loop | 4 +-- .../test-bug-679371-apt-get-autoclean-multiarch | 4 +-- .../test-bug-686346-package-missing-architecture | 4 +-- ...bug-712116-dpkg-pre-install-pkgs-hook-multiarch | 2 +- .../test-bug-717891-abolute-uris-for-proxies | 4 +-- test/integration/test-compressed-indexes | 34 +++++++++++----------- .../test-cve-2013-1051-InRelease-parsing | 2 +- test/integration/test-disappearing-packages | 2 +- test/integration/test-pdiff-usage | 4 +-- test/integration/test-policy-pinning | 8 ++--- test/integration/test-releasefile-valid-until | 32 ++++++++++---------- .../test-ubuntu-bug-761175-remove-purge | 6 ++-- ...st-ubuntu-bug-784473-InRelease-one-message-only | 2 +- 26 files changed, 125 insertions(+), 93 deletions(-) diff --git a/test/integration/framework b/test/integration/framework index f64b8482c..e363977f5 100644 --- a/test/integration/framework +++ b/test/integration/framework @@ -928,6 +928,40 @@ testmarkedauto() { aptmark showauto 2>&1 | checkdiff $COMPAREFILE - && msgpass || msgfail } +testsuccess() { + if [ "$1" = '--nomsg' ]; then + shift + else + msgtest 'Test for successful execution of' "$*" + fi + local OUTPUT=$(mktemp) + addtrap "rm $OUTPUT;" + if $@ >${OUTPUT} 2>&1; then + msgpass + else + echo + cat $OUTPUT + msgfail + fi +} + +testfailure() { + if [ "$1" = '--nomsg' ]; then + shift + else + msgtest 'Test for failure in execution of' "$*" + fi + local OUTPUT=$(mktemp) + addtrap "rm $OUTPUT;" + if $@ >${OUTPUT} 2>&1; then + echo + cat $OUTPUT + msgfail + else + msgpass + fi +} + pause() { echo "STOPPED execution. Press enter to continue" local IGNORE diff --git a/test/integration/test-apt-cdrom b/test/integration/test-apt-cdrom index 6e3533152..85c3a2fee 100755 --- a/test/integration/test-apt-cdrom +++ b/test/integration/test-apt-cdrom @@ -102,5 +102,5 @@ aptcache show testing -o Acquire::Languages=en | grep -q '^Description-en: ' && # check that we really can install from a 'cdrom' testdpkgnotinstalled testing -aptget install testing -y > /dev/null 2>&1 +testsuccess aptget install testing -y testdpkginstalled testing diff --git a/test/integration/test-apt-get-autoremove b/test/integration/test-apt-get-autoremove index c25ce3f58..dc30cde34 100755 --- a/test/integration/test-apt-get-autoremove +++ b/test/integration/test-apt-get-autoremove @@ -11,11 +11,11 @@ buildsimplenativepackage 'po-debconf' 'all' '1.0.16' 'unstable' buildsimplenativepackage 'debhelper' 'all' '8.0.0' 'unstable' 'Depends: po-debconf' setupaptarchive -aptget install unrelated debhelper -qq 2>&1 > /dev/null +testsuccess aptget install unrelated debhelper -y testdpkginstalled 'unrelated' 'debhelper' 'po-debconf' testmarkedauto 'po-debconf' -aptget remove debhelper -y -qq 2>&1 > /dev/null +testsuccess aptget remove debhelper -y testdpkgnotinstalled 'debhelper' testdpkginstalled 'po-debconf' 'unrelated' @@ -30,15 +30,15 @@ Remv po-debconf [1.0.16]' aptget autoremove -s testdpkginstalled 'po-debconf' echo 'APT::NeverAutoRemove { "^po-debconf$"; };' > rootdir/etc/apt/apt.conf.d/00autoremove -aptget autoremove -y -qq 2>&1 > /dev/null +testsuccess aptget autoremove -y testdpkginstalled 'po-debconf' echo 'APT::NeverAutoRemove { "^po-.*$"; };' > rootdir/etc/apt/apt.conf.d/00autoremove -aptget autoremove -y -qq 2>&1 > /dev/null +testsuccess aptget autoremove -y testdpkginstalled "po-debconf" rm rootdir/etc/apt/apt.conf.d/00autoremove -aptget autoremove -y -qq 2>&1 > /dev/null +testsuccess aptget autoremove -y testdpkgnotinstalled 'po-debconf' testmarkedauto diff --git a/test/integration/test-bug-407511-fail-invalid-default-release b/test/integration/test-bug-407511-fail-invalid-default-release index 7f23a1e82..3d3b0ada3 100755 --- a/test/integration/test-bug-407511-fail-invalid-default-release +++ b/test/integration/test-bug-407511-fail-invalid-default-release @@ -35,14 +35,14 @@ setupaptarchive passdist() { msgtest 'Test that target-release is accepted' $1 - aptget dist-upgrade -t $1 -qq && msgpass || msgfail + testsuccess --nomsg aptget dist-upgrade -t $1 msgtest 'Test that target-release pins with' $1 aptcache policy -t $1 | grep -q ' 990' && msgpass || msgfail } faildist() { msgtest 'Test that target-release is refused' $1 - aptget dist-upgrade -t $1 -qq 2> /dev/null && msgfail || msgpass + testfailure --nomsg aptget dist-upgrade -t $1 } msgtest 'Test that no default-release is active in this test' 'setup' diff --git a/test/integration/test-bug-602412-dequote-redirect b/test/integration/test-bug-602412-dequote-redirect index c20443559..764e13667 100755 --- a/test/integration/test-bug-602412-dequote-redirect +++ b/test/integration/test-bug-602412-dequote-redirect @@ -16,7 +16,7 @@ mv aptarchive/pool aptarchive/newpool mv aptarchive/dists aptarchive/newdists msgtest 'Test redirection works in' 'apt-get update' -aptget update -qq && msgpass || msgfail +testsuccess --nomsg aptget update # check that I-M-S header is kept in redirections testequal 'Hit http://localhost:8080 unstable InRelease @@ -26,4 +26,4 @@ Hit http://localhost:8080 unstable/main Translation-en Reading package lists...' aptget update #-o debug::pkgacquire=1 -o debug::pkgacquire::worker=1 msgtest 'Test redirection works in' 'package download' -aptget install unrelated --download-only -qq && msgpass || msgfail +testsuccess --nomsg aptget install unrelated --download-only diff --git a/test/integration/test-bug-604222-new-and-autoremove b/test/integration/test-bug-604222-new-and-autoremove index ea73c5775..b29347f64 100755 --- a/test/integration/test-bug-604222-new-and-autoremove +++ b/test/integration/test-bug-604222-new-and-autoremove @@ -8,7 +8,7 @@ configarchitecture "i386" setupaptarchive touch rootdir/var/lib/apt/extended_states -aptmark markauto 'libvtk5.4' +testsuccess aptmark markauto 'libvtk5.4' testmarkedauto 'libvtk5.4' testequal "Reading package lists... diff --git a/test/integration/test-bug-604401-files-are-directories b/test/integration/test-bug-604401-files-are-directories index aae717a19..e6913edcf 100755 --- a/test/integration/test-bug-604401-files-are-directories +++ b/test/integration/test-bug-604401-files-are-directories @@ -11,7 +11,7 @@ test ! -e rootdir/etc/apt/apt.conf || mv rootdir/etc/apt/apt.conf rootdir/etc/ap msgtest "Directory instead of a file as apt.conf ignored" mkdir -p rootdir/etc/apt/apt.conf -aptconfig dump > /dev/null && msgpass || msgfail +testsuccess --nomsg aptconfig dump rmdir rootdir/etc/apt/apt.conf msgtest "Good link instead of a file as apt.conf ignored" @@ -22,7 +22,7 @@ rm rootdir/etc/apt/apt.conf msgtest "Broken link instead of a file as apt.conf ignored" ln -s /tmp/doesnt-exist rootdir/etc/apt/apt.conf -aptconfig dump > /dev/null && msgpass || msgfail +testsuccess --nomsg aptconfig dump rm rootdir/etc/apt/apt.conf @@ -30,7 +30,7 @@ test ! -e rootdir/etc/apt/sources.list || mv rootdir/etc/apt/sources.list rootdi msgtest "Directory instead of a file as sources.list ignored" mkdir -p rootdir/etc/apt/sources.list -aptget update --print-uris 2> /dev/null && msgpass || msgfail +testsuccess --nomsg aptget update --print-uris rmdir rootdir/etc/apt/sources.list msgtest "Good link instead of a file as sources.list ignored" @@ -49,7 +49,7 @@ test ! -e rootdir/etc/apt/preferences || mv rootdir/etc/apt/preferences rootdir/ msgtest "Directory instead of a file as preferences ignored" mkdir -p rootdir/etc/apt/preferences -aptcache policy > /dev/null 2> /dev/null && msgpass || msgfail +testsuccess --nomsg aptcache policy rmdir rootdir/etc/apt/preferences msgtest "Good link instead of a file as preferences ignored" @@ -62,5 +62,5 @@ rm rootdir/etc/apt/preferences msgtest "Broken link instead of a file as preferences ignored" ln -s /tmp/doesnt-exist rootdir/etc/apt/preferences -aptcache policy > /dev/null 2> /dev/null && msgpass || msgfail +testsuccess --nomsg aptcache policy rm rootdir/etc/apt/preferences diff --git a/test/integration/test-bug-611729-mark-as-manual b/test/integration/test-bug-611729-mark-as-manual index 9cf01610c..e3d454f97 100755 --- a/test/integration/test-bug-611729-mark-as-manual +++ b/test/integration/test-bug-611729-mark-as-manual @@ -15,21 +15,21 @@ buildsimplenativepackage "c" "all" "1.0" "stable" "Depends: b" setupaptarchive # dpkg freaks out if the last package is removed so keep one around -aptget install peace-dpkg -y -qq 2>&1 > /dev/null +testsuccess aptget install peace-dpkg -y testdpkginstalled peace-dpkg testmarkedauto -aptget install a -y -qq 2>&1 > /dev/null +testsuccess aptget install a -y testdpkginstalled a b testdpkgnotinstalled c testmarkedauto 'b' -aptget remove a -y -qq 2>&1 > /dev/null +testsuccess aptget remove a -y testdpkgnotinstalled a c testdpkginstalled b testmarkedauto 'b' -aptget install c -y -qq 2>&1 > /dev/null +testsuccess aptget install c -y testdpkgnotinstalled a testdpkginstalled b c testmarkedauto 'b' @@ -50,7 +50,7 @@ testmarkedauto 'b' rm rootdir/var/log/apt/history.log -aptget install b --reinstall -y -qq 2>&1 > /dev/null +testsuccess aptget install b --reinstall -y testdpkgnotinstalled a testdpkginstalled b c testmarkedauto 'b' @@ -67,24 +67,24 @@ b set to manually installed. 0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.' aptget install b testmarkedauto -aptget remove b -y -qq 2>&1 > /dev/null +testsuccess aptget remove b -y testdpkgnotinstalled a b c testmarkedauto -aptget install a b -y -qq 2>&1 > /dev/null +testsuccess aptget install a b -y testdpkginstalled a b testdpkgnotinstalled c testmarkedauto -aptget purge a b -y -qq 2>&1 > /dev/null +testsuccess aptget purge a b -y testdpkgnotinstalled a b c testmarkedauto -aptget install b c -y -qq 2>&1 > /dev/null +testsuccess aptget install b c -y testdpkgnotinstalled a testdpkginstalled b c testmarkedauto -aptget install a -y -qq 2>&1 > /dev/null +testsuccess aptget install a -y testdpkginstalled a b c testmarkedauto diff --git a/test/integration/test-bug-612099-multiarch-conflicts b/test/integration/test-bug-612099-multiarch-conflicts index 530012e5d..b91804826 100755 --- a/test/integration/test-bug-612099-multiarch-conflicts +++ b/test/integration/test-bug-612099-multiarch-conflicts @@ -15,7 +15,7 @@ buildsimplenativepackage 'foobar' 'amd64' '1.0' 'stable' 'Depends: libc6' setupaptarchive -aptget install libc6:i386 -t stable -y -qq 2>&1 > /dev/null +testsuccess aptget install libc6:i386 -t stable -y testdpkginstalled libc6:i386 testequal 'Reading package lists... Building dependency tree... @@ -79,8 +79,8 @@ Conf libc6 (2.0 testing [all])' aptget upgrade -t testing -s # as APT (here i386) disagree about the native architecture, so # we fake it here: #aptget upgrade -y -qq 2>&1 > /dev/null -aptget purge libc6 -y -qq 2>&1 >/dev/null -aptget install libc6:i386 -y -qq 2>&1 >/dev/null +testsuccess aptget purge libc6 -y +testsuccess aptget install libc6:i386 -y testdpkginstalled libc6:all testequal 'Reading package lists... @@ -129,7 +129,7 @@ buildsimplenativepackage 'foobar-same' 'amd64' '1.0' 'stable' 'Depends: libc6-sa setupaptarchive -aptget install libc6-same:i386 -t stable -y -qq 2>&1 > /dev/null +testsuccess aptget install libc6-same:i386 -t stable -y testdpkginstalled libc6-same:i386 testequal 'Reading package lists... @@ -177,8 +177,8 @@ Conf libc6-same (2.0 testing [all])' aptget upgrade -t testing -s # as APT (here i386) disagree about the native architecture, so # we fake it here: #aptget upgrade -y -qq 2>&1 > /dev/null -aptget purge libc6-same -y -qq 2>&1 >/dev/null -aptget install libc6-same:i386 -y -qq 2>&1 >/dev/null +testsuccess aptget purge libc6-same -y +testsuccess aptget install libc6-same:i386 -y testdpkginstalled libc6-same:all diff --git a/test/integration/test-bug-612557-garbage-upgrade b/test/integration/test-bug-612557-garbage-upgrade index 8efd1687a..910b3b149 100755 --- a/test/integration/test-bug-612557-garbage-upgrade +++ b/test/integration/test-bug-612557-garbage-upgrade @@ -13,7 +13,7 @@ insertpackage 'unstable' 'libreoffice-common' 'all' '1:3.3.0-2' 'Conflicts: open setupaptarchive touch rootdir/var/lib/apt/extended_states -aptmark markauto python-uno openoffice.org-common +testsuccess aptmark markauto python-uno openoffice.org-common #aptmark unmarkauto openoffice.org-emailmerge testmarkedauto python-uno openoffice.org-common @@ -32,7 +32,7 @@ The following packages will be upgraded: After this operation, 53.2 MB disk space will be freed. E: Trivial Only specified but this is not a trivial operation.' aptget --trivial-only install python-uno -aptmark markauto openoffice.org-emailmerge +testsuccess aptmark markauto openoffice.org-emailmerge testmarkedauto python-uno openoffice.org-common openoffice.org-emailmerge testequal 'Reading package lists... diff --git a/test/integration/test-bug-612958-use-dpkg-multiarch-config b/test/integration/test-bug-612958-use-dpkg-multiarch-config index 18b964636..4d1f00ca0 100755 --- a/test/integration/test-bug-612958-use-dpkg-multiarch-config +++ b/test/integration/test-bug-612958-use-dpkg-multiarch-config @@ -14,13 +14,13 @@ insertinstalledpackage 'libapt' 'armel' '1.0' testpass() { rm rootdir/var/cache/apt/*.bin msgtest 'Test architecture handling' "$1 with $2" - aptcache show libapt:$2 2> /dev/null > /dev/null && msgpass || msgfail + testsuccess --nomsg aptcache show libapt:$2 } testfail() { rm rootdir/var/cache/apt/*.bin msgtest 'Test architecture handling' "$1 with $2" - aptcache show libapt:$2 2> /dev/null > /dev/null && msgfail || msgpass + testfailure --nomsg aptcache show libapt:$2 } testpass 'no config' 'i386' diff --git a/test/integration/test-bug-613420-new-garbage-dependency b/test/integration/test-bug-613420-new-garbage-dependency index 7a08871ca..9d9f1096a 100755 --- a/test/integration/test-bug-613420-new-garbage-dependency +++ b/test/integration/test-bug-613420-new-garbage-dependency @@ -15,7 +15,7 @@ insertpackage 'unstable' 'openoffice.org-officebean' 'all' '1:3.3.0-5' 'Depends: setupaptarchive touch rootdir/var/lib/apt/extended_states -aptmark markauto openoffice.org-officebean +testsuccess aptmark markauto openoffice.org-officebean testmarkedauto openoffice.org-officebean testequal "Reading package lists... diff --git a/test/integration/test-bug-64141-install-dependencies-for-on-hold b/test/integration/test-bug-64141-install-dependencies-for-on-hold index e2d206fdd..9a9e7be10 100755 --- a/test/integration/test-bug-64141-install-dependencies-for-on-hold +++ b/test/integration/test-bug-64141-install-dependencies-for-on-hold @@ -31,7 +31,7 @@ The following packages will be upgraded: After this operation, 0 B of additional disk space will be used. E: Trivial Only specified but this is not a trivial operation.' aptget dist-upgrade --trivial-only -aptmark hold apt -qq +testsuccess aptmark hold apt testequal 'Reading package lists... Building dependency tree... diff --git a/test/integration/test-bug-673536-pre-depends-breaks-loop b/test/integration/test-bug-673536-pre-depends-breaks-loop index e9d3c4de6..f6a90b21f 100755 --- a/test/integration/test-bug-673536-pre-depends-breaks-loop +++ b/test/integration/test-bug-673536-pre-depends-breaks-loop @@ -15,9 +15,9 @@ setupaptarchive # we check with 'real' packages here as the simulation reports a 'Conf broken' # which is technical correct for the simulation, but testing errormsg is ugly -aptget install basic=1 -qq > /dev/null +testsuccess aptget install basic=1 -y testdpkginstalled basic testdpkgnotinstalled common -aptget dist-upgrade -qq > /dev/null +testsuccess aptget dist-upgrade -y testdpkginstalled basic common diff --git a/test/integration/test-bug-679371-apt-get-autoclean-multiarch b/test/integration/test-bug-679371-apt-get-autoclean-multiarch index ba6857b73..b62d437aa 100755 --- a/test/integration/test-bug-679371-apt-get-autoclean-multiarch +++ b/test/integration/test-bug-679371-apt-get-autoclean-multiarch @@ -14,8 +14,8 @@ setupaptarchive changetowebserver -aptget update -qq -aptget install pkgall pkgnative pkgforeign -y -qq > /dev/null +testsuccess aptget update +testsuccess aptget install pkgall pkgnative pkgforeign -y testdpkginstalled pkgall pkgnative pkgforeign diff --git a/test/integration/test-bug-686346-package-missing-architecture b/test/integration/test-bug-686346-package-missing-architecture index b2c9ec9ee..3b02811ca 100755 --- a/test/integration/test-bug-686346-package-missing-architecture +++ b/test/integration/test-bug-686346-package-missing-architecture @@ -58,13 +58,13 @@ Building dependency tree... # pkgd has no update with an architecture testdpkginstalled pkgd msgtest 'Test apt-get purge' 'pkgd' -aptget purge pkgd -y >/dev/null 2>&1 && msgpass || msgfail +testsuccess --nomsg aptget purge pkgd -y testdpkgnotinstalled pkgd # there is a pkgb with an architecture testdpkginstalled pkgb msgtest 'Test apt-get purge' 'pkgb:none' -aptget purge pkgb:none -y >/dev/null 2>&1 && msgpass || msgfail +testsuccess --nomsg aptget purge pkgb:none -y testdpkgnotinstalled pkgb # check that dependencies are created after the none package exists in the cache diff --git a/test/integration/test-bug-712116-dpkg-pre-install-pkgs-hook-multiarch b/test/integration/test-bug-712116-dpkg-pre-install-pkgs-hook-multiarch index a89cb7191..af65397ea 100755 --- a/test/integration/test-bug-712116-dpkg-pre-install-pkgs-hook-multiarch +++ b/test/integration/test-bug-712116-dpkg-pre-install-pkgs-hook-multiarch @@ -42,7 +42,7 @@ enablehookversion 3 observehook() { rm -f ${hook}-v2.list ${hook}-v3.list msgtest 'Observe hooks while' "$*" - aptget "$@" -y --force-yes >/dev/null 2>&1 && msgpass || msgfail + testsuccess --nomsg aptget "$@" -y --force-yes } observehook install stuff -t stable diff --git a/test/integration/test-bug-717891-abolute-uris-for-proxies b/test/integration/test-bug-717891-abolute-uris-for-proxies index e9c38492e..ac1d6ec11 100755 --- a/test/integration/test-bug-717891-abolute-uris-for-proxies +++ b/test/integration/test-bug-717891-abolute-uris-for-proxies @@ -12,12 +12,12 @@ setupaptarchive changetowebserver --request-absolute='uri' msgtest 'Check that absolute paths are' 'not accepted' -aptget update >/dev/null 2>&1 && msgfail || msgpass +testfailure --nomsg aptget update echo 'Acquire::http::Proxy "http://localhost:8080";' > rootdir/etc/apt/apt.conf.d/99proxy msgtest 'Check that requests to proxies are' 'absolute uris' -aptget update >/dev/null 2>&1 && msgpass || msgfail +testsuccess --nomsg aptget update testequal 'Reading package lists... Building dependency tree... diff --git a/test/integration/test-compressed-indexes b/test/integration/test-compressed-indexes index a5e885745..c6f5ab49e 100755 --- a/test/integration/test-compressed-indexes +++ b/test/integration/test-compressed-indexes @@ -46,10 +46,10 @@ testrun() { msgpass fi msgtest "Check if package is downloadable" - aptget install -d testpkg -qq && msgpass || msgfail - msgtest "\tdeb file is present"; test -f rootdir/var/cache/apt/archives/testpkg_1.0_i386.deb && msgpass || msgfail + testsuccess --nomsg aptget install -d testpkg + msgtest "\tdeb file is present"; testsuccess --nomsg test -f rootdir/var/cache/apt/archives/testpkg_1.0_i386.deb aptget clean - msgtest "\tdeb file is gone"; ! test -f rootdir/var/cache/apt/archives/testpkg_1.0_i386.deb && msgpass || msgfail + msgtest "\tdeb file is gone"; testfailure --nomsg test -f rootdir/var/cache/apt/archives/testpkg_1.0_i386.deb fi rm -f rootdir/var/cache/apt/pkgcache.bin rootdir/var/cache/apt/srcpkgcache.bin testequal "$GOODSHOW" aptcache show testpkg @@ -62,9 +62,9 @@ testrun() { testequal "$GOODSHOWSRC" aptcache showsrc testpkg aptget clean msgtest "Check if the source is aptgetable" - aptget source testpkg -qq 2> /dev/null > /dev/null && msgpass || msgfail - msgtest "\tdsc file is present"; test -f testpkg_1.0.dsc && msgpass || msgfail - msgtest "\tdirectory is present"; test -d testpkg-1.0 && msgpass || msgfail + testsuccess --nomsg aptget source testpkg + msgtest "\tdsc file is present"; testsuccess --nomsg test -f testpkg_1.0.dsc + msgtest "\tdirectory is present"; testsuccess --nomsg test -d testpkg-1.0 rm -rf testpkg-1.0 } @@ -72,11 +72,11 @@ echo 'Acquire::GzipIndexes "false";' > rootdir/etc/apt/apt.conf.d/02compressinde msgmsg "File: Test with uncompressed indexes" testrun -aptget update -qq -o Acquire::Pdiffs=1 +testsuccess aptget update -o Acquire::Pdiffs=1 msgmsg "File: Test with uncompressed indexes (update unchanged with pdiffs)" testrun -aptget update -qq -o Acquire::Pdiffs=0 +testsuccess aptget update -o Acquire::Pdiffs=0 msgmsg "File: Test with uncompressed indexes (update unchanged without pdiffs)" testrun @@ -84,21 +84,21 @@ rm -rf rootdir/var/lib/apt/lists echo 'Acquire::CompressionTypes::Order:: "gz"; Acquire::GzipIndexes "true";' > rootdir/etc/apt/apt.conf.d/02compressindex -aptget update -qq +testsuccess aptget update msgmsg "File: Test with compressed indexes" testrun "compressed" -aptget update -qq -o Acquire::Pdiffs=1 +testsuccess aptget update -o Acquire::Pdiffs=1 msgmsg "File: Test with compressed indexes (update unchanged with pdiffs)" testrun "compressed" -aptget update -qq -o Acquire::Pdiffs=0 +testsuccess aptget update -o Acquire::Pdiffs=0 msgmsg "File: Test with compressed indexes (update unchanged without pdiffs)" testrun "compressed" rm rootdir/etc/apt/apt.conf.d/02compressindex changetowebserver -aptget update -qq +testsuccess aptget update GOODPOLICY="$(aptcache policy testpkg)" test $(echo "$GOODPOLICY" | grep -e '^testpkg:' -e '^ Candidate:' -e '^ Installed: (none)' -e '500 http://' | wc -l) -eq 4 testequal "$GOODPOLICY" aptcache policy testpkg @@ -106,11 +106,11 @@ testequal "$GOODPOLICY" aptcache policy testpkg msgmsg "HTTP: Test with uncompressed indexes" testrun -aptget update -qq -o Acquire::Pdiffs=1 +testsuccess aptget update -o Acquire::Pdiffs=1 msgmsg "HTTP: Test with uncompressed indexes (update unchanged with pdiffs)" testrun -aptget update -qq -o Acquire::Pdiffs=0 +testsuccess aptget update -o Acquire::Pdiffs=0 msgmsg "HTTP: Test with uncompressed indexes (update unchanged without pdiffs)" testrun @@ -118,14 +118,14 @@ rm -rf rootdir/var/lib/apt/lists echo 'Acquire::CompressionTypes::Order:: "gz"; Acquire::GzipIndexes "true";' > rootdir/etc/apt/apt.conf.d/02compressindex -aptget update -qq +testsuccess aptget update msgmsg "HTTP: Test with compressed indexes" testrun "compressed" -aptget update -qq -o Acquire::Pdiffs=1 +testsuccess aptget update -o Acquire::Pdiffs=1 msgmsg "HTTP: Test with compressed indexes (update unchanged with pdiffs)" testrun "compressed" -aptget update -qq -o Acquire::Pdiffs=0 +testsuccess aptget update -o Acquire::Pdiffs=0 msgmsg "HTTP: Test with compressed indexes (update unchanged without pdiffs)" testrun "compressed" diff --git a/test/integration/test-cve-2013-1051-InRelease-parsing b/test/integration/test-cve-2013-1051-InRelease-parsing index 6764fefff..41b27f691 100755 --- a/test/integration/test-cve-2013-1051-InRelease-parsing +++ b/test/integration/test-cve-2013-1051-InRelease-parsing @@ -14,7 +14,7 @@ setupaptarchive changetowebserver ARCHIVE='http://localhost:8080/' msgtest 'Initial apt-get update should work with' 'InRelease' -aptget update -qq && msgpass || msgfail +testsuccess --nomsg aptget update # check that the setup is correct testequal "good-pkg: diff --git a/test/integration/test-disappearing-packages b/test/integration/test-disappearing-packages index d2ac4edc6..09dbf7014 100755 --- a/test/integration/test-disappearing-packages +++ b/test/integration/test-disappearing-packages @@ -29,7 +29,7 @@ rm -rf "$BUILDDIR" setupaptarchive -aptget install old-pkg=1.0 --trivial-only -qq 2>&1 > /dev/null +testsuccess aptget install old-pkg=1.0 --trivial-only testmarkedauto # old-pkg is manual installed diff --git a/test/integration/test-pdiff-usage b/test/integration/test-pdiff-usage index e45326970..994489ee5 100755 --- a/test/integration/test-pdiff-usage +++ b/test/integration/test-pdiff-usage @@ -11,7 +11,7 @@ buildaptarchive setupflataptarchive changetowebserver signreleasefiles -aptget update -qq +testsuccess aptget update testnopackage newstuff PKGFILE="${TESTDIR}/$(echo "$(basename $0)" | sed 's#^test-#Packages-#')" @@ -38,7 +38,7 @@ SHA1-Patches: generatereleasefiles '+1hour' signreleasefiles find aptarchive -name 'Packages*' -type f -delete -aptget update -qq +testsuccess aptget update testnopackage oldstuff testequal "$(cat ${PKGFILE}-new) diff --git a/test/integration/test-policy-pinning b/test/integration/test-policy-pinning index 9e1ea4ac5..8eb4bcbad 100755 --- a/test/integration/test-policy-pinning +++ b/test/integration/test-policy-pinning @@ -228,16 +228,16 @@ testequalpolicycoolstuff "" "2.0~bpo1" 990 500 600 "2.0~bpo1" -o Test=ButAutomat testequalpolicycoolstuff "" "1.0" 100 990 600 "2.0~bpo1" -o Test=ButAutomaticUpgrades -t stable rm rootdir/etc/apt/preferences -aptget install coolstuff -qq > /dev/null 2> /dev/null +testsuccess aptget install coolstuff -y testequalpolicycoolstuff "1.0" "1.0" 100 500 0 "" -o Test=ButAutomaticUpgrades -aptget dist-upgrade -qq > /dev/null 2> /dev/null +testsuccess aptget dist-upgrade -y testequalpolicycoolstuff "1.0" "1.0" 100 500 0 "" -o Test=ButAutomaticUpgrades testequalpolicycoolstuff "1.0" "1.0" 100 990 0 "" -o Test=ButAutomaticUpgrades -t stable testequalpolicycoolstuff "1.0" "2.0~bpo1" 990 500 0 "" -o Test=ButAutomaticUpgrades -t backports -aptget install coolstuff -t backports -qq > /dev/null 2> /dev/null +testsuccess aptget install coolstuff -t backports -y testequalpolicycoolstuff "2.0~bpo1" "2.0~bpo1" 100 500 0 "" -o Test=ButAutomaticUpgrades -aptget dist-upgrade -qq > /dev/null 2> /dev/null +testsuccess aptget dist-upgrade -y testequalpolicycoolstuff "2.0~bpo1" "2.0~bpo1" 100 500 0 "" -o Test=ButAutomaticUpgrades testequalpolicycoolstuff "2.0~bpo1" "2.0~bpo1" 100 990 0 "" -o Test=ButAutomaticUpgrades -t stable testequalpolicycoolstuff "2.0~bpo1" "2.0~bpo1" 990 500 0 "" -o Test=ButAutomaticUpgrades -t backports diff --git a/test/integration/test-releasefile-valid-until b/test/integration/test-releasefile-valid-until index 680a370cb..e673d5f71 100755 --- a/test/integration/test-releasefile-valid-until +++ b/test/integration/test-releasefile-valid-until @@ -32,64 +32,64 @@ aptgetupdate() { setupreleasefile msgtest 'Release file is accepted as it has' 'no Until' -aptgetupdate && msgpass || msgfail +testsuccess --nomsg aptgetupdate setupreleasefile msgtest 'Release file is accepted as it has' 'no Until and good Max-Valid' -aptgetupdate -o Acquire::Max-ValidTime=3600 && msgpass || msgfail +testsuccess --nomsg aptgetupdate -o Acquire::Max-ValidTime=3600 setupreleasefile 'now - 2 days' msgtest 'Release file is rejected as it has' 'no Until, but bad Max-Valid' -aptgetupdate -o Acquire::Max-ValidTime=3600 && msgfail || msgpass +testfailure --nomsg aptgetupdate -o Acquire::Max-ValidTime=3600 setupreleasefile 'now - 3 days' 'now + 1 day' msgtest 'Release file is accepted as it has' 'good Until' -aptgetupdate && msgpass || msgfail +testsuccess --nomsg aptgetupdate setupreleasefile 'now - 7 days' 'now - 4 days' msgtest 'Release file is rejected as it has' 'bad Until' -aptgetupdate && msgfail || msgpass +testfailure --nomsg aptgetupdate setupreleasefile 'now - 7 days' 'now - 4 days' msgtest 'Release file is rejected as it has' 'bad Until (ignore good Max-Valid)' -aptgetupdate -o Acquire::Max-ValidTime=1209600 && msgfail || msgpass +testfailure --nomsg aptgetupdate -o Acquire::Max-ValidTime=1209600 setupreleasefile 'now - 7 days' 'now - 4 days' msgtest 'Release file is rejected as it has' 'bad Max-Valid (bad Until)' -aptgetupdate -o Acquire::Max-ValidTime=86400 && msgfail || msgpass +testfailure --nomsg aptgetupdate -o Acquire::Max-ValidTime=86400 setupreleasefile 'now - 7 days' 'now + 4 days' msgtest 'Release file is rejected as it has' 'bad Max-Valid (good Until)' -aptgetupdate -o Acquire::Max-ValidTime=86400 && msgfail || msgpass +testfailure --nomsg aptgetupdate -o Acquire::Max-ValidTime=86400 setupreleasefile 'now - 7 days' 'now + 4 days' msgtest 'Release file is accepted as it has' 'good labeled Max-Valid' -aptgetupdate -o Acquire::Max-ValidTime=86400 -o Acquire::Max-ValidTime::Testcases=1209600 && msgpass || msgfail +testsuccess --nomsg aptgetupdate -o Acquire::Max-ValidTime=86400 -o Acquire::Max-ValidTime::Testcases=1209600 setupreleasefile 'now - 7 days' 'now + 4 days' msgtest 'Release file is rejected as it has' 'bad labeled Max-Valid' -aptgetupdate -o Acquire::Max-ValidTime=1209600 -o Acquire::Max-ValidTime::Testcases=86400 && msgfail || msgpass +testfailure --nomsg aptgetupdate -o Acquire::Max-ValidTime=1209600 -o Acquire::Max-ValidTime::Testcases=86400 setupreleasefile 'now - 7 days' 'now + 1 days' msgtest 'Release file is accepted as it has' 'good Until (good Min-Valid, no Max-Valid)' -aptgetupdate -o Acquire::Min-ValidTime=1209600 && msgpass || msgfail +testsuccess --nomsg aptgetupdate -o Acquire::Min-ValidTime=1209600 setupreleasefile 'now - 7 days' 'now - 4 days' msgtest 'Release file is accepted as it has' 'good Min-Valid (bad Until, no Max-Valid)' -aptgetupdate -o Acquire::Min-ValidTime=1209600 && msgpass || msgfail +testsuccess --nomsg aptgetupdate -o Acquire::Min-ValidTime=1209600 setupreleasefile 'now - 7 days' 'now - 2 days' msgtest 'Release file is accepted as it has' 'good Min-Valid (bad Until, good Max-Valid) <' -aptgetupdate -o Acquire::Min-ValidTime=1209600 -o Acquire::Max-ValidTime=2419200 && msgpass || msgfail +testsuccess --nomsg aptgetupdate -o Acquire::Min-ValidTime=1209600 -o Acquire::Max-ValidTime=2419200 setupreleasefile 'now - 7 days' 'now - 2 days' msgtest 'Release file is rejected as it has' 'bad Max-Valid (bad Until, good Min-Valid) >' -aptgetupdate -o Acquire::Max-ValidTime=12096 -o Acquire::Min-ValidTime=2419200 && msgfail || msgpass +testfailure --nomsg aptgetupdate -o Acquire::Max-ValidTime=12096 -o Acquire::Min-ValidTime=2419200 setupreleasefile 'now - 7 days' 'now - 2 days' msgtest 'Release file is rejected as it has' 'bad Max-Valid (bad Until, bad Min-Valid) <' -aptgetupdate -o Acquire::Min-ValidTime=12096 -o Acquire::Max-ValidTime=241920 && msgfail || msgpass +testfailure --nomsg aptgetupdate -o Acquire::Min-ValidTime=12096 -o Acquire::Max-ValidTime=241920 setupreleasefile 'now - 7 days' 'now - 2 days' msgtest 'Release file is rejected as it has' 'bad Max-Valid (bad Until, bad Min-Valid) >' -aptgetupdate -o Acquire::Max-ValidTime=12096 -o Acquire::Min-ValidTime=241920 && msgfail || msgpass +testfailure --nomsg aptgetupdate -o Acquire::Max-ValidTime=12096 -o Acquire::Min-ValidTime=241920 diff --git a/test/integration/test-ubuntu-bug-761175-remove-purge b/test/integration/test-ubuntu-bug-761175-remove-purge index f55c6e909..14648e9b8 100755 --- a/test/integration/test-ubuntu-bug-761175-remove-purge +++ b/test/integration/test-ubuntu-bug-761175-remove-purge @@ -18,12 +18,10 @@ setupaptarchive testdpkgnotinstalled compiz-core -msgtest 'Install package' 'compiz-core' -aptget install compiz-core -qq 2>&1 >/dev/null && msgpass || msgfail +testsuccess aptget install compiz-core testdpkginstalled compiz-core -msgtest 'Remove package' 'compiz-core' -aptget remove compiz-core -y -qq 2>&1 >/dev/null && msgpass || msgfail +testsuccess aptget remove compiz-core -y testdpkgnotinstalled compiz-core msgtest 'Check that conffiles are still around for' 'compiz-core' diff --git a/test/integration/test-ubuntu-bug-784473-InRelease-one-message-only b/test/integration/test-ubuntu-bug-784473-InRelease-one-message-only index fad5488fb..e9d684309 100755 --- a/test/integration/test-ubuntu-bug-784473-InRelease-one-message-only +++ b/test/integration/test-ubuntu-bug-784473-InRelease-one-message-only @@ -28,7 +28,7 @@ MD5Sum: done msgtest 'The unsigned garbage before signed block is' 'ignored' -aptget update -qq > /dev/null 2>&1 && msgpass || msgfail +testsuccess --nomsg aptget update ROOTDIR="$(readlink -f .)" testequal "Package files: -- cgit v1.2.3 From ffcccd62f0d5822a71e24baf84126af5c93a5e69 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 10 Aug 2013 12:40:37 +0200 Subject: fix: --print-uris removes authentication MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The constructors of our (clear)sign-acquire-items move a pre-existent file for error-recovery away, which gets restored or discarded later as the acquire progresses, but --print-uris never really starts the acquire process, so the files aren't restored (as they should). To fix this both get a destructor which checks for signs of acquire doing anything and if it hasn't the file is restored. Note that these virtual destructors theoretically break the API, but only with classes extending the sign-acquire-items and nobody does this, as it would be insane for library users to fiddle with Acquire internals – and these classes are internals. Closes: 719263 --- apt-pkg/acquire-item.cc | 31 +++++++++++++--- apt-pkg/acquire-item.h | 2 ++ test/integration/test-bug-602412-dequote-redirect | 2 +- ...st-bug-719263-print-uris-removes-authentication | 41 ++++++++++++++++++++++ 4 files changed, 71 insertions(+), 5 deletions(-) create mode 100755 test/integration/test-bug-719263-print-uris-removes-authentication diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 7bcdf285b..95dadcd6d 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -1067,8 +1067,7 @@ pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire *Owner, /*{{{*/ string Final = _config->FindDir("Dir::State::lists"); Final += URItoFileName(RealURI); - struct stat Buf; - if (stat(Final.c_str(),&Buf) == 0) + if (RealFileExists(Final) == true) { // File was already in place. It needs to be re-downloaded/verified // because Release might have changed, we do give it a differnt @@ -1080,6 +1079,19 @@ pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire *Owner, /*{{{*/ } QueueURI(Desc); +} + /*}}}*/ +pkgAcqMetaSig::~pkgAcqMetaSig() /*{{{*/ +{ + // if the file was never queued undo file-changes done in the constructor + if (QueueCounter == 1 && Status == StatIdle && FileSize == 0 && Complete == false && + LastGoodSig.empty() == false) + { + string const Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI); + if (RealFileExists(Final) == false && RealFileExists(LastGoodSig) == true) + Rename(LastGoodSig, Final); + } + } /*}}}*/ // pkgAcqMetaSig::Custom600Headers - Insert custom request headers /*{{{*/ @@ -1595,14 +1607,25 @@ pkgAcqMetaClearSig::pkgAcqMetaClearSig(pkgAcquire *Owner, /*{{{*/ // keep the old InRelease around in case of transistent network errors string const Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI); - struct stat Buf; - if (stat(Final.c_str(),&Buf) == 0) + if (RealFileExists(Final) == true) { string const LastGoodSig = DestFile + ".reverify"; Rename(Final,LastGoodSig); } } /*}}}*/ +pkgAcqMetaClearSig::~pkgAcqMetaClearSig() /*{{{*/ +{ + // if the file was never queued undo file-changes done in the constructor + if (QueueCounter == 1 && Status == StatIdle && FileSize == 0 && Complete == false) + { + string const Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI); + string const LastGoodSig = DestFile + ".reverify"; + if (RealFileExists(Final) == false && RealFileExists(LastGoodSig) == true) + Rename(LastGoodSig, Final); + } +} + /*}}}*/ // pkgAcqMetaClearSig::Custom600Headers - Insert custom request headers /*{{{*/ // --------------------------------------------------------------------- // FIXME: this can go away once the InRelease file is used widely diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index 51d539450..10c855e63 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -774,6 +774,7 @@ class pkgAcqMetaSig : public pkgAcquire::Item std::string MetaIndexURI, std::string MetaIndexURIDesc, std::string MetaIndexShortDesc, const std::vector* IndexTargets, indexRecords* MetaIndexParser); + virtual ~pkgAcqMetaSig(); }; /*}}}*/ /** \brief An item that is responsible for downloading the meta-index {{{ @@ -904,6 +905,7 @@ public: std::string const &MetaSigURI, std::string const &MetaSigURIDesc, std::string const &MetaSigShortDesc, const std::vector* IndexTargets, indexRecords* MetaIndexParser); + virtual ~pkgAcqMetaClearSig(); }; /*}}}*/ /** \brief An item that is responsible for fetching a package file. {{{ diff --git a/test/integration/test-bug-602412-dequote-redirect b/test/integration/test-bug-602412-dequote-redirect index 764e13667..bcebb57b8 100755 --- a/test/integration/test-bug-602412-dequote-redirect +++ b/test/integration/test-bug-602412-dequote-redirect @@ -26,4 +26,4 @@ Hit http://localhost:8080 unstable/main Translation-en Reading package lists...' aptget update #-o debug::pkgacquire=1 -o debug::pkgacquire::worker=1 msgtest 'Test redirection works in' 'package download' -testsuccess --nomsg aptget install unrelated --download-only +testsuccess --nomsg aptget install unrelated --download-only -y diff --git a/test/integration/test-bug-719263-print-uris-removes-authentication b/test/integration/test-bug-719263-print-uris-removes-authentication new file mode 100755 index 000000000..1c1a27ceb --- /dev/null +++ b/test/integration/test-bug-719263-print-uris-removes-authentication @@ -0,0 +1,41 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework + +setupenvironment +configarchitecture 'amd64' + +insertinstalledpackage 'unrelated' 'all' '1' +buildsimplenativepackage 'unrelated' 'all' '2' 'unstable' + +setupaptarchive + +testnoact() { + cp -a rootdir/var/lib/dpkg/status rootdir/var/lib/dpkg/status-backup-noact + touch rootdir/var/lib/apt/extended_states + testequal 'Reading package lists... +Building dependency tree... +Reading state information... +The following packages will be upgraded: + unrelated +1 upgraded, 0 newly installed, 0 to remove and 0 not upgraded. +Inst unrelated [1] (2 unstable [all]) +Conf unrelated (2 unstable [all])' aptget install unrelated -s + testsuccess aptget install unrelated -y + testdpkginstalled unrelated + cp -a rootdir/var/lib/dpkg/status-backup-noact rootdir/var/lib/dpkg/status +} + +testnoact +testsuccess aptget update --print-uris +testnoact + +# same thing, just not with InRelease this time +rm -rf rootdir/var/lib/apt/lists +testsuccess aptget update -o Acquire::TryInRelease=0 + +testnoact +testsuccess aptget update --print-uris -o Acquire::TryInRelease=0 +testnoact -- cgit v1.2.3 From 7a2690a3bf59244fff417ab494f68fd9301b74d9 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 13 Jul 2013 22:57:44 +0200 Subject: fix output redirection order First redirect output to a file, then redirect other outputs to this output, not the other way around as this will not work. Git-Dch: Ignore --- test/integration/framework | 6 +++--- test/integration/skip-avoid-avoiding-breaks-predepends | 2 +- test/integration/test-bug-612099-multiarch-conflicts | 4 ++-- test/integration/test-bug-618288-multiarch-same-lockstep | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/test/integration/framework b/test/integration/framework index e363977f5..005e31bd3 100644 --- a/test/integration/framework +++ b/test/integration/framework @@ -177,7 +177,7 @@ setupenvironment() { echo "DPKG::options:: \"--root=${TMPWORKINGDIRECTORY}/rootdir\";" >> aptconfig.conf echo "DPKG::options:: \"--force-not-root\";" >> aptconfig.conf echo "DPKG::options:: \"--force-bad-path\";" >> aptconfig.conf - if ! $(which dpkg) --assert-multi-arch 2>&1 > /dev/null; then + if ! $(which dpkg) --assert-multi-arch >/dev/null 2>&1; then echo "DPKG::options:: \"--force-architecture\";" >> aptconfig.conf # Added to test multiarch before dpkg is ready for it… fi echo "DPKG::options:: \"--log=${TMPWORKINGDIRECTORY}/rootdir/var/log/dpkg.log\";" >> aptconfig.conf @@ -225,7 +225,7 @@ configdpkg() { echo -n > rootdir/var/lib/dpkg/status fi fi - if $(which dpkg) --assert-multi-arch 2>&1 > /dev/null; then + if $(which dpkg) --assert-multi-arch >/dev/null 2>&1; then local ARCHS="$(getarchitectures)" if echo "$ARCHS" | grep -E -q '[^ ]+ [^ ]+'; then DPKGARCH="$(dpkg --print-architecture)" @@ -851,7 +851,7 @@ testequalor2() { echo "$2" > $COMPAREFILE2 shift 2 msgtest "Test for equality OR of" "$*" - $* 2>&1 1> $COMPAREAGAINST + $* >$COMPAREAGAINST 2>&1 (checkdiff $COMPAREFILE1 $COMPAREAGAINST 1> /dev/null || checkdiff $COMPAREFILE2 $COMPAREAGAINST 1> /dev/null) && msgpass || ( echo "\n${CINFO}Diff against OR 1${CNORMAL}" "$(checkdiff $COMPAREFILE1 $COMPAREAGAINST)" \ diff --git a/test/integration/skip-avoid-avoiding-breaks-predepends b/test/integration/skip-avoid-avoiding-breaks-predepends index a47e8bc2b..ed231bc3f 100755 --- a/test/integration/skip-avoid-avoiding-breaks-predepends +++ b/test/integration/skip-avoid-avoiding-breaks-predepends @@ -17,5 +17,5 @@ Pre-Depends: looping (>= 1.15)' setupaptarchive -aptget dist-upgrade -y -o Debug::pkgOrderList=1 #-qq 2>&1 > /dev/null +aptget dist-upgrade -y -o Debug::pkgOrderList=1 #-qq >/dev/null 2>&1 testdpkginstalled looping loop1 loop2 diff --git a/test/integration/test-bug-612099-multiarch-conflicts b/test/integration/test-bug-612099-multiarch-conflicts index b91804826..20dc3a7e5 100755 --- a/test/integration/test-bug-612099-multiarch-conflicts +++ b/test/integration/test-bug-612099-multiarch-conflicts @@ -78,7 +78,7 @@ Conf libc6 (2.0 testing [all])' aptget upgrade -t testing -s # FIXME: on amd64 systems this test wouldn't run with a real upgrade # as APT (here i386) disagree about the native architecture, so # we fake it here: -#aptget upgrade -y -qq 2>&1 > /dev/null +#aptget upgrade -y -qq >/dev/null 2>&1 testsuccess aptget purge libc6 -y testsuccess aptget install libc6:i386 -y testdpkginstalled libc6:all @@ -176,7 +176,7 @@ Conf libc6-same (2.0 testing [all])' aptget upgrade -t testing -s # FIXME: on amd64 systems this test wouldn't run with a real upgrade # as APT (here i386) disagree about the native architecture, so # we fake it here: -#aptget upgrade -y -qq 2>&1 > /dev/null +#aptget upgrade -y -qq >/dev/null 2>&1 testsuccess aptget purge libc6-same -y testsuccess aptget install libc6-same:i386 -y testdpkginstalled libc6-same:all diff --git a/test/integration/test-bug-618288-multiarch-same-lockstep b/test/integration/test-bug-618288-multiarch-same-lockstep index fde075172..e0305b64b 100755 --- a/test/integration/test-bug-618288-multiarch-same-lockstep +++ b/test/integration/test-bug-618288-multiarch-same-lockstep @@ -16,7 +16,7 @@ buildsimplenativepackage 'apt' 'i386' '2' 'unstable' 'Depends: libsame (= 2)' '' buildsimplenativepackage 'apt2' 'amd64' '2' 'unstable' 'Depends: libsame (= 2)' '' 'required' setupaptarchive -aptget dist-upgrade -s 2>&1 > output.apt +aptget dist-upgrade -s >output.apt 2>&1 # order in switch libsame:{amd64,i386} are unpacked is irrelevant, as both are installed - but we need to do it together LS_U_AMD="$(grep -o -n '^Inst libsame ' output.apt | cut -d: -f1)" -- cgit v1.2.3 From 11b126f9d229c85bfc7a6092527af46f7314f188 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 13 Jul 2013 23:05:55 +0200 Subject: do not try to chown if not run as root MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If this code is run as non-root we are in a special situation (e.g. in our testcases) where it is obvious that we can't enforce user/group on any file, so skip this code altogether instead of bugging users with an error message – which we also switch to a warning as a failure to open the file is "just" a warning, so the 'wrong' owner shouldn't be that much of an issue. The file is still handled with chmod, so all the security we can enforce is still enforced of course, which also gets a warning if it fails. Git-Dch: Ignore --- apt-pkg/deb/dpkgpm.cc | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 34ae4e593..5b2a8251e 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -751,14 +751,15 @@ bool pkgDPkgPM::OpenLog() return _error->WarningE("OpenLog", _("Could not open file '%s'"), logfile_name.c_str()); setvbuf(d->term_out, NULL, _IONBF, 0); SetCloseExec(fileno(d->term_out), true); - struct passwd *pw; - struct group *gr; - pw = getpwnam("root"); - gr = getgrnam("adm"); - if (pw != NULL && gr != NULL) - if(chown(logfile_name.c_str(), pw->pw_uid, gr->gr_gid) != 0) - _error->Errno("OpenLog", "chown failed"); - chmod(logfile_name.c_str(), 0640); + if (getuid() == 0) // if we aren't root, we can't chown a file, so don't try it + { + struct passwd *pw = getpwnam("root"); + struct group *gr = getgrnam("adm"); + if (pw != NULL && gr != NULL && chown(logfile_name.c_str(), pw->pw_uid, gr->gr_gid) != 0) + _error->WarningE("OpenLog", "chown to root:adm of file %s failed", logfile_name.c_str()); + } + if (chmod(logfile_name.c_str(), 0640) != 0) + _error->WarningE("OpenLog", "chmod 0640 of file %s failed", logfile_name.c_str()); fprintf(d->term_out, "\nLog started: %s\n", timestr); } -- cgit v1.2.3 From 87281603a1342a7dc4d12f979574704a45bf6b7b Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 13 Jul 2013 23:14:41 +0200 Subject: use our _error stack to generate openpty errors While we don't want these error messages on our usual stack, we can use our usual infrastructure to generate an error message with all the usual bells like errno and strerror attached. Git-Dch: Ignore --- apt-pkg/deb/dpkgpm.cc | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 5b2a8251e..959d06455 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1238,16 +1238,13 @@ bool pkgDPkgPM::Go(int OutStatusFd) // if tcgetattr does not return zero there was a error // and we do not do any pty magic - if (tcgetattr(0, &tt) == 0) + _error->PushToStack(); + if (tcgetattr(STDOUT_FILENO, &tt) == 0) { ioctl(0, TIOCGWINSZ, (char *)&win); - if (openpty(&master, &slave, NULL, &tt, &win) < 0) + if (openpty(&master, &slave, NULL, &tt, &win) < 0) { - const char *s = _("Can not write log, openpty() " - "failed (/dev/pts not mounted?)\n"); - fprintf(stderr, "%s",s); - if(d->term_out) - fprintf(d->term_out, "%s",s); + _error->Errno("openpty", _("Can not write log (%s)"), _("Is /dev/pts mounted?")); master = slave = -1; } else { struct termios rtt; @@ -1265,6 +1262,15 @@ bool pkgDPkgPM::Go(int OutStatusFd) sigprocmask(SIG_SETMASK, &original_sigmask, 0); } } + // complain only if stdout is either a terminal (but still failed) or is an invalid + // descriptor otherwise we would complain about redirection to e.g. /dev/null as well. + else if (isatty(STDOUT_FILENO) == 1 || errno == EBADF) + _error->Errno("tcgetattr", _("Can not write log (%s)"), _("Is stdout a terminal?")); + + if (_error->PendingError() == true) + _error->DumpErrors(std::cerr); + _error->RevertToStack(); + // Fork dpkg pid_t Child; _config->Set("APT::Keep-Fds::",fd[1]); -- cgit v1.2.3 From 3dc55197095e0536aae4d5c0c91e28bfd4740ec6 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 11 Jul 2013 19:20:09 +0200 Subject: add a not documented apt-key --fakeroot option Usually, most apt-key commands require root, so the script is checking for being run as root, but in your tests we use a non-root location, so we don't need to be root and therefore need an option to skip the check. Git-Dch: Ignore --- cmdline/apt-key | 73 ++++++++++++++++++++++++++++++++------------------------- 1 file changed, 41 insertions(+), 32 deletions(-) diff --git a/cmdline/apt-key b/cmdline/apt-key index 2c087acbc..89e224923 100755 --- a/cmdline/apt-key +++ b/cmdline/apt-key @@ -158,39 +158,48 @@ usage() { echo "If no specific keyring file is given the command applies to all keyring files." } -# Determine on which keyring we want to work -if [ "$1" = "--keyring" ]; then - #echo "keyfile given" - shift - TRUSTEDFILE="$1" - if [ -r "$TRUSTEDFILE" ] || [ "$2" = 'add' ] || [ "$2" = 'adv' ]; then - GPG="$GPG --keyring $TRUSTEDFILE --primary-keyring $TRUSTEDFILE" - else - echo >&2 "Error: The specified keyring »$TRUSTEDFILE« is missing or not readable" - exit 1 - fi - shift -# otherwise use the default -else - #echo "generate list" - TRUSTEDFILE="/etc/apt/trusted.gpg" - eval $(apt-config shell TRUSTEDFILE Apt::GPGV::TrustedKeyring) - eval $(apt-config shell TRUSTEDFILE Dir::Etc::Trusted/f) - if [ -r "$TRUSTEDFILE" ]; then - GPG="$GPG --keyring $TRUSTEDFILE" - fi - GPG="$GPG --primary-keyring $TRUSTEDFILE" - TRUSTEDPARTS="/etc/apt/trusted.gpg.d" - eval $(apt-config shell TRUSTEDPARTS Dir::Etc::TrustedParts/d) - if [ -d "$TRUSTEDPARTS" ]; then - #echo "parts active" - for trusted in $(run-parts --list $TRUSTEDPARTS --regex '^.*\.gpg$'); do - #echo "part -> $trusted" - GPG="$GPG --keyring $trusted" - done - fi +while [ -n "$1" ]; do + case "$1" in + --keyring) + shift + TRUSTEDFILE="$1" + if [ -r "$TRUSTEDFILE" ] || [ "$2" = 'add' ] || [ "$2" = 'adv' ]; then + GPG="$GPG --keyring $TRUSTEDFILE --primary-keyring $TRUSTEDFILE" + else + echo >&2 "Error: The specified keyring »$TRUSTEDFILE« is missing or not readable" + exit 1 + fi + shift + ;; + --fakeroot) + requires_root() { true; } + shift + ;; + --*) + echo >&2 "Unknown option: $1" + usage + exit 1;; + *) + break;; + esac +done + +if [ -z "$TRUSTEDFILE" ]; then + TRUSTEDFILE="/etc/apt/trusted.gpg" + eval $(apt-config shell TRUSTEDFILE Apt::GPGV::TrustedKeyring) + eval $(apt-config shell TRUSTEDFILE Dir::Etc::Trusted/f) + if [ -r "$TRUSTEDFILE" ]; then + GPG="$GPG --keyring $TRUSTEDFILE" + fi + GPG="$GPG --primary-keyring $TRUSTEDFILE" + TRUSTEDPARTS="/etc/apt/trusted.gpg.d" + eval $(apt-config shell TRUSTEDPARTS Dir::Etc::TrustedParts/d) + if [ -d "$TRUSTEDPARTS" ]; then + for trusted in $(run-parts --list $TRUSTEDPARTS --regex '^.*\.gpg$'); do + GPG="$GPG --keyring $trusted" + done + fi fi -#echo "COMMAND: $GPG" command="$1" if [ -z "$command" ]; then -- cgit v1.2.3 From c0a013221d296e97d68b4e9a66fef5c886d2bbb0 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 11 Jul 2013 20:07:22 +0200 Subject: always use our own trustdb.gpg in apt-key APT doesn't care for the trustdb.gpg, but gnupg requires one even for the simplest commands, so we either use the one root has available in /etc or if we don't have access to it (as only root can read that file) we create a temporary directory to store a trustdb.gpg in it. We can't create just a temporary file as gpg requires the given trustdb.gpg file to be valid (if it exists), so we would have to remove the file before calling gnupg which would allow mktemp (and co) to hand exactly this filename out to another program (unlikely, but still). --- cmdline/apt-key | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/cmdline/apt-key b/cmdline/apt-key index 89e224923..4596e4a47 100755 --- a/cmdline/apt-key +++ b/cmdline/apt-key @@ -6,15 +6,23 @@ unset GREP_OPTIONS # We don't use a secret keyring, of course, but gpg panics and # implodes if there isn't one available SECRETKEYRING="$(mktemp)" -trap "rm -f '${SECRETKEYRING}'" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM +CURRENTTRAP="rm -f '${SECRETKEYRING}';" +trap "${CURRENTTRAP}" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM GPG_CMD="gpg --ignore-time-conflict --no-options --no-default-keyring --secret-keyring ${SECRETKEYRING}" -if [ "$(id -u)" -eq 0 ]; then - # we could use a tmpfile here too, but creation of this tends to be time-consuming - eval $(apt-config shell TRUSTDBDIR Dir::Etc/d) - GPG_CMD="$GPG_CMD --trustdb-name ${TRUSTDBDIR}/trustdb.gpg" +eval $(apt-config shell TRUSTDBDIR Dir::Etc/d) +if [ "$(id -u)" -eq 0 ] || [ -r "${TRUSTDBDIR}/trustdb.gpg" ]; then + # root can read/create the file as needed, so use the default + true +else + # gpg needs a trustdb to function, but it can't be invalid (not even empty) + # so we create a tempory directory to store our fresh readable trustdb in + TRUSTDBDIR="$(mktemp -d)" + CURRENTTRAP="${CURRENTTRAP} rm -rf '${TRUSTDBDIR}';" + trap "${CURRENTTRAP}" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM + chmod 700 "$TRUSTDBDIR" fi - +GPG_CMD="$GPG_CMD --trustdb-name ${TRUSTDBDIR}/trustdb.gpg" GPG="$GPG_CMD" MASTER_KEYRING="" -- cgit v1.2.3 From f9e64e7bb0c125b54f0699d9e08956a88b467a7f Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 12 Aug 2013 00:19:10 +0200 Subject: use a tmpfile for trustdb.gpg in apt-key MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit for some "interesting" reason gpg decides that it needs to update its trustdb.gpg file in a --list-keys command even if right before gpg is asked to --check-trustdb. That wouldn't be as bad if it wouldn't modify the keyring being listed at that moment as well, which generates not only warnings which are not a problem for us, but as the keyring modified can be in /usr it modified files which aren't allowed to be modified. The suggested solution in the bugreport is running --check-trustdb unconditionally in an 'apt-key update' call, but this command will not be used in the future and this could still potentially bite us in net-update or adv calls. All of this just to keep a file around, which we do not need… The commit therefore switches to the use of a temporary created trusted.gpg file for everyone and asks gpg to not try to update the trustdb after its intial creation, which seems to avoid the problem altogether. It is using your also faked secring btw as calling the check-trustdb without a keyring is a lot slower … Closes: #687611 Thanks: Andreas Beckmann for the initial patch! --- cmdline/apt-key | 36 ++++++++++++++++++------------------ debian/apt.postinst | 13 +++++++++---- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/cmdline/apt-key b/cmdline/apt-key index 4596e4a47..e010e6e90 100755 --- a/cmdline/apt-key +++ b/cmdline/apt-key @@ -3,26 +3,26 @@ set -e unset GREP_OPTIONS -# We don't use a secret keyring, of course, but gpg panics and -# implodes if there isn't one available -SECRETKEYRING="$(mktemp)" -CURRENTTRAP="rm -f '${SECRETKEYRING}';" -trap "${CURRENTTRAP}" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM -GPG_CMD="gpg --ignore-time-conflict --no-options --no-default-keyring --secret-keyring ${SECRETKEYRING}" +GPG_CMD="gpg --ignore-time-conflict --no-options --no-default-keyring" -eval $(apt-config shell TRUSTDBDIR Dir::Etc/d) -if [ "$(id -u)" -eq 0 ] || [ -r "${TRUSTDBDIR}/trustdb.gpg" ]; then - # root can read/create the file as needed, so use the default - true -else - # gpg needs a trustdb to function, but it can't be invalid (not even empty) - # so we create a tempory directory to store our fresh readable trustdb in - TRUSTDBDIR="$(mktemp -d)" - CURRENTTRAP="${CURRENTTRAP} rm -rf '${TRUSTDBDIR}';" - trap "${CURRENTTRAP}" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM - chmod 700 "$TRUSTDBDIR" -fi +# gpg needs a trustdb to function, but it can't be invalid (not even empty) +# so we create a temporary directory to store our fresh readable trustdb in +TRUSTDBDIR="$(mktemp -d)" +CURRENTTRAP="${CURRENTTRAP} rm -rf '${TRUSTDBDIR}';" +trap "${CURRENTTRAP}" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM +chmod 700 "$TRUSTDBDIR" +# We also don't use a secret keyring, of course, but gpg panics and +# implodes if there isn't one available - and writeable for imports +SECRETKEYRING="${TRUSTDBDIR}/secring.gpg" +touch $SECRETKEYRING +GPG_CMD="$GPG_CMD --secret-keyring $SECRETKEYRING" GPG_CMD="$GPG_CMD --trustdb-name ${TRUSTDBDIR}/trustdb.gpg" + +# now create the trustdb with an (empty) dummy keyring +$GPG_CMD --quiet --check-trustdb --keyring $SECRETKEYRING +# and make sure that gpg isn't trying to update the file +GPG_CMD="$GPG_CMD --no-auto-check-trustdb --trust-model always" + GPG="$GPG_CMD" MASTER_KEYRING="" diff --git a/debian/apt.postinst b/debian/apt.postinst index 9ff1e031c..caa05ccdf 100644 --- a/debian/apt.postinst +++ b/debian/apt.postinst @@ -15,10 +15,15 @@ set -e case "$1" in configure) - SECRING='/etc/apt/secring.gpg' - # test if secring is an empty normal file - if test -f $SECRING -a ! -s $SECRING; then - rm -f $SECRING + if dpkg --compare-versions "$2" lt-nl 0.9.9.5; then + # we are using tmpfiles for both + rm -f /etc/apt/trustdb.gpg + # this removal was done unconditional since 0.8.15.3 + SECRING='/etc/apt/secring.gpg' + # test if secring is an empty normal file + if test -f $SECRING -a ! -s $SECRING; then + rm -f $SECRING + fi fi apt-key update -- cgit v1.2.3 From 59f46f3ace16e769383a61ee336a76c6d03931ea Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 12 Aug 2013 00:33:37 +0200 Subject: do not double-slash paths in apt-key Closes: 665411 --- cmdline/apt-key | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cmdline/apt-key b/cmdline/apt-key index e010e6e90..7038be265 100755 --- a/cmdline/apt-key +++ b/cmdline/apt-key @@ -203,7 +203,12 @@ if [ -z "$TRUSTEDFILE" ]; then TRUSTEDPARTS="/etc/apt/trusted.gpg.d" eval $(apt-config shell TRUSTEDPARTS Dir::Etc::TrustedParts/d) if [ -d "$TRUSTEDPARTS" ]; then - for trusted in $(run-parts --list $TRUSTEDPARTS --regex '^.*\.gpg$'); do + # strip / suffix as gpg will double-slash in that case (#665411) + STRIPPED_TRUSTEDPARTS="${TRUSTEDPARTS%/}" + if [ "${STRIPPED_TRUSTEDPARTS}/" = "$TRUSTEDPARTS" ]; then + TRUSTEDPARTS="$STRIPPED_TRUSTEDPARTS" + fi + for trusted in $(run-parts --list "$TRUSTEDPARTS" --regex '^.*\.gpg$'); do GPG="$GPG --keyring $trusted" done fi -- cgit v1.2.3 From 80f3aeb04d043356bd98de7714fc164b3fff3861 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 12 Aug 2013 00:36:52 +0200 Subject: make the keyring locations in apt-key configurable Might come in handy for more than just a simple testcase. --- cmdline/apt-key | 6 +++++- test/integration/test-apt-key | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100755 test/integration/test-apt-key diff --git a/cmdline/apt-key b/cmdline/apt-key index 7038be265..a9cbea55c 100755 --- a/cmdline/apt-key +++ b/cmdline/apt-key @@ -26,12 +26,16 @@ GPG_CMD="$GPG_CMD --no-auto-check-trustdb --trust-model always" GPG="$GPG_CMD" MASTER_KEYRING="" -ARCHIVE_KEYRING_URI="" #MASTER_KEYRING=/usr/share/keyrings/debian-master-keyring.gpg +eval $(apt-config shell MASTER_KEYRING APT::Key::MasterKeyring) +ARCHIVE_KEYRING_URI="" #ARCHIVE_KEYRING_URI=http://ftp.debian.org/debian/debian-archive-keyring.gpg +eval $(apt-config shell ARCHIVE_KEYRING_URI APT::Key::ArchiveKeyringURI) ARCHIVE_KEYRING=/usr/share/keyrings/debian-archive-keyring.gpg +eval $(apt-config shell ARCHIVE_KEYRING APT::Key::ArchiveKeyring) REMOVED_KEYS=/usr/share/keyrings/debian-archive-removed-keys.gpg +eval $(apt-config shell REMOVED_KEYS APT::Key::RemovedKeys) requires_root() { if [ "$(id -u)" -ne 0 ]; then diff --git a/test/integration/test-apt-key b/test/integration/test-apt-key new file mode 100755 index 000000000..5beb6f220 --- /dev/null +++ b/test/integration/test-apt-key @@ -0,0 +1,39 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework + +setupenvironment +configarchitecture 'amd64' + +msgtest 'Check that paths in list output are not' 'double-slashed' +aptkey list 2>&1 | grep -q '//' && msgfail || msgpass + +msgtest 'Check that paths in finger output are not' 'double-slashed' +aptkey finger 2>&1 | grep -q '//' && msgfail || msgpass + +echo 'APT::Key::ArchiveKeyring "./keys/joesixpack.pub"; +APT::Key::RemovedKeys "./keys/rexexpired.pub";' > rootdir/etc/apt/apt.conf.d/aptkey.conf + +aptkey list | grep '^pub' > aptkey.list +testfileequal ./aptkey.list 'pub 2048R/DBAC8DAE 2010-08-18' + +testequal 'gpg: key DBAC8DAE: "Joe Sixpack (APT Testcases Dummy) " not changed +gpg: Total number processed: 1 +gpg: unchanged: 1' aptkey --fakeroot update + +aptkey list | grep '^pub' > aptkey.list +testfileequal ./aptkey.list 'pub 2048R/DBAC8DAE 2010-08-18' + +testsuccess aptkey --fakeroot add ./keys/rexexpired.pub + +aptkey list | grep '^pub' > aptkey.list +testfileequal ./aptkey.list 'pub 2048R/27CE74F9 2013-07-12 [expired: 2013-07-13] +pub 2048R/DBAC8DAE 2010-08-18' + +msgtest 'Execute update again to trigger removal of' 'Rex Expired key' +testsuccess --nomsg aptkey --fakeroot update + +aptkey list | grep '^pub' > aptkey.list +testfileequal ./aptkey.list 'pub 2048R/DBAC8DAE 2010-08-18' -- cgit v1.2.3 From 804d4a0d92a2e107aad38198ac08f1d2d64b5e53 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 12 Aug 2013 15:51:42 +0200 Subject: ensure that testcases exiting because of set -e aren't successful Git-Dch: Ignore --- test/integration/framework | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/test/integration/framework b/test/integration/framework index 005e31bd3..72c899e32 100644 --- a/test/integration/framework +++ b/test/integration/framework @@ -131,13 +131,23 @@ exitwithstatus() { exit $((EXIT_CODE <= 255 ? EXIT_CODE : 255)); } +shellsetedetector() { + local exit_status=$? + if [ "$exit_status" != '0' ]; then + echo >&2 "${CERROR}E: Looks like the testcases ended prematurely with exitcode: ${exit_status}${CNORMAL}" + if [ "$EXIT_CODE" = '0' ]; then + EXIT_CODE="$exit_status" + fi + fi +} + addtrap() { if [ "$1" = 'prefix' ]; then CURRENTTRAP="$2 $CURRENTTRAP" else CURRENTTRAP="$CURRENTTRAP $1" fi - trap "$CURRENTTRAP exitwithstatus;" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM + trap "shellsetedetector; $CURRENTTRAP exitwithstatus;" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM } setupenvironment() { -- cgit v1.2.3 From 04937adc655ceda0b3367f540e76df10296cfba1 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 12 Aug 2013 16:19:37 +0200 Subject: let apt-key del work better with softlink and single key keyrings Having fragement files means there is a good chance that there is one key per keyring, so deal with that as well as with setups in which keyrings are linked into trusted.gpg.d as we can't just modify those files (they might be in /usr for example). --- cmdline/apt-key | 59 +++++++++++++++++++++++++++++++++++-- test/integration/test-apt-key | 68 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+), 3 deletions(-) diff --git a/cmdline/apt-key b/cmdline/apt-key index a9cbea55c..713a41c07 100755 --- a/cmdline/apt-key +++ b/cmdline/apt-key @@ -151,6 +151,60 @@ update() { fi } +remove_key_from_keyring() { + local GPG="$GPG_CMD --keyring $1" + # check if the key is in this keyring: the key id is in the 5 column at the end + if ! $GPG --with-colons --list-keys 2>&1 | grep -q "^pub:[^:]*:[^:]*:[^:]*:[0-9A-F]\+$2:"; then + return + fi + if [ ! -w "$1" ]; then + echo >&2 "Key ${2} is in keyring ${1}, but can't be removed as it is read only." + return + fi + # check if it is the only key in the keyring and if so remove the keyring alltogether + if [ '1' = "$($GPG --with-colons --list-keys | grep "^pub:[^:]*:[^:]*:[^:]*:[0-9A-F]\+:" | wc -l)" ]; then + mv -f "$1" "${1}~" # behave like gpg + return + fi + # we can't just modify pointed to files as these might be in /usr or something + local REALTARGET + if [ -L "$1" ]; then + REALTARGET="$(readlink -f "$1")" + mv -f "$1" "${1}.dpkg-tmp" + cp -a "$REALTARGET" "$1" + ls "$(dirname $1)" + fi + # delete the key from the keyring + $GPG --batch --delete-key --yes "$2" + if [ -n "$REALTARGET" ]; then + # the real backup is the old link, not the copy we made + mv -f "${1}.dpkg-tmp" "${1}~" + fi +} + +remove_key() { + requires_root + + # if a --keyring was given, just remove from there + if [ -n "$FORCED_KEYRING" ]; then + remove_key_from_keyring "$FORCED_KEYRING" "$1" + else + # otherwise all known keyrings are up for inspection + local TRUSTEDFILE="/etc/apt/trusted.gpg" + eval $(apt-config shell TRUSTEDFILE Apt::GPGV::TrustedKeyring) + eval $(apt-config shell TRUSTEDFILE Dir::Etc::Trusted/f) + remove_key_from_keyring "$TRUSTEDFILE" "$1" + TRUSTEDPARTS="/etc/apt/trusted.gpg.d" + eval $(apt-config shell TRUSTEDPARTS Dir::Etc::TrustedParts/d) + if [ -d "$TRUSTEDPARTS" ]; then + for trusted in $(run-parts --list "$TRUSTEDPARTS" --regex '^.*\.gpg$'); do + remove_key_from_keyring "$trusted" "$1" + done + fi + fi + echo "OK" +} + usage() { echo "Usage: apt-key [--keyring file] [command] [arguments]" @@ -175,6 +229,7 @@ while [ -n "$1" ]; do --keyring) shift TRUSTEDFILE="$1" + FORCED_KEYRING="$1" if [ -r "$TRUSTEDFILE" ] || [ "$2" = 'add' ] || [ "$2" = 'adv' ]; then GPG="$GPG --keyring $TRUSTEDFILE --primary-keyring $TRUSTEDFILE" else @@ -239,10 +294,8 @@ case "$command" in echo "OK" ;; del|rm|remove) - requires_root init_keyring "$TRUSTEDFILE" - $GPG --quiet --batch --delete-key --yes "$1" - echo "OK" + remove_key "$1" ;; update) init_keyring "$TRUSTEDFILE" diff --git a/test/integration/test-apt-key b/test/integration/test-apt-key index 5beb6f220..68b3f9710 100755 --- a/test/integration/test-apt-key +++ b/test/integration/test-apt-key @@ -37,3 +37,71 @@ testsuccess --nomsg aptkey --fakeroot update aptkey list | grep '^pub' > aptkey.list testfileequal ./aptkey.list 'pub 2048R/DBAC8DAE 2010-08-18' + +msgtest "Try to remove a key which exists, but isn't in the" 'forced keyring' +testsuccess --nomsg aptkey --fakeroot --keyring rootdir/etc/apt/trusted.gpg del DBAC8DAE + +aptkey list | grep '^pub' > aptkey.list +testfileequal ./aptkey.list 'pub 2048R/DBAC8DAE 2010-08-18' + +testsuccess aptkey --fakeroot del DBAC8DAE +testempty aptkey list + +# start from a clean plate again +cleanplate() { + rm -rf rootdir/etc/apt/trusted.gpg.d/ rootdir/etc/apt/trusted.gpg + mkdir rootdir/etc/apt/trusted.gpg.d/ +} + +msgtest 'Test key removal with' 'single key in real file' +cleanplate +cp -a keys/joesixpack.pub rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg +testsuccess --nomsg aptkey --fakeroot del DBAC8DAE +testempty aptkey list +testsuccess test ! -e rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg +testsuccess cmp keys/joesixpack.pub rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg~ + +msgtest 'Test key removal with' 'single key in softlink' +cleanplate +ln -s $(readlink -f ./keys/joesixpack.pub) rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg +testsuccess --nomsg aptkey --fakeroot del DBAC8DAE +testempty aptkey list +testsuccess test ! -e rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg +testsuccess test -L rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg~ + +cleanplate +testsuccess aptkey --fakeroot add ./keys/joesixpack.pub +testsuccess aptkey --fakeroot add ./keys/marvinparanoid.pub +aptkey list | grep '^pub' > aptkey.list +testfileequal ./aptkey.list 'pub 2048R/DBAC8DAE 2010-08-18 +pub 2048R/528144E2 2011-01-16' +cp -a rootdir/etc/apt/trusted.gpg keys/testcase-multikey.pub # store for reuse + +msgtest 'Test key removal with' 'multi key in real file' +cleanplate +cp -a keys/testcase-multikey.pub rootdir/etc/apt/trusted.gpg.d/multikey.gpg +testsuccess --nomsg aptkey --fakeroot del DBAC8DAE +aptkey list | grep '^pub' > aptkey.list +testfileequal ./aptkey.list 'pub 2048R/528144E2 2011-01-16' +testsuccess cmp keys/testcase-multikey.pub rootdir/etc/apt/trusted.gpg.d/multikey.gpg~ + +msgtest 'Test key removal with' 'multi key in softlink' +cleanplate +ln -s $(readlink -f ./keys/testcase-multikey.pub) rootdir/etc/apt/trusted.gpg.d/multikey.gpg +testsuccess --nomsg aptkey --fakeroot del DBAC8DAE +aptkey list | grep '^pub' > aptkey.list +testfileequal ./aptkey.list 'pub 2048R/528144E2 2011-01-16' +testsuccess cmp keys/testcase-multikey.pub rootdir/etc/apt/trusted.gpg.d/multikey.gpg~ +testsuccess test ! -L rootdir/etc/apt/trusted.gpg.d/multikey.gpg +testsuccess test -L rootdir/etc/apt/trusted.gpg.d/multikey.gpg~ + +msgtest 'Test key removal with' 'multiple files including key' +cleanplate +cp -a keys/joesixpack.pub rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg +cp -a keys/testcase-multikey.pub rootdir/etc/apt/trusted.gpg.d/multikey.gpg +testsuccess --nomsg aptkey --fakeroot del DBAC8DAE +aptkey list | grep '^pub' > aptkey.list +testfileequal ./aptkey.list 'pub 2048R/528144E2 2011-01-16' +testsuccess test ! -e rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg +testsuccess cmp keys/joesixpack.pub rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg~ +testsuccess cmp keys/testcase-multikey.pub rootdir/etc/apt/trusted.gpg.d/multikey.gpg~ -- cgit v1.2.3 From ec9272975f454d3911e61e5cc3b29fe90fe2ee54 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 12 Aug 2013 17:26:54 +0200 Subject: do not call 'apt-key update' in apt.postinst The debian-archive-keyring package ships trusted.gpg.d fragment files for a while now and dropped their call to 'apt-key update', so there is no need for use to call it as the keys will always be available. This also finally allows a user to remove key(ring)s without APT to overriding this decision by readding them with this step. The functionality is kept around in the odd case that an old debian-archive-keyring package is used which still calls 'apt-key update' and depends on the import (hence, we also do not enforce a newer version of the debian-archive-keyring via our dependencies) --- debian/apt.postinst | 1 - 1 file changed, 1 deletion(-) diff --git a/debian/apt.postinst b/debian/apt.postinst index caa05ccdf..70de237d0 100644 --- a/debian/apt.postinst +++ b/debian/apt.postinst @@ -25,7 +25,6 @@ case "$1" in rm -f $SECRING fi fi - apt-key update # ensure tighter permissons on the logs, see LP: #975199 if dpkg --compare-versions "$2" lt-nl 0.9.7.7; then -- cgit v1.2.3 From 713a2de01cc1a0b8dcd71a4137f8a099d22783b7 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 12 Aug 2013 21:45:59 +0200 Subject: update changelog for upload --- debian/changelog | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index d1ecbff1f..8e4def2b0 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,9 +1,48 @@ -apt (0.9.9.5) UNRELEASED; urgency=low +apt (0.9.10) unstable; urgency=low + The "Hello to Debconf" upload + + [ Christian Perrier ] * Vietnamese translation update. Closes: #718615 * Japanese translation update. Closes: #719279 - -- Christian Perrier Sat, 03 Aug 2013 16:06:55 +0200 + [ Michael Vogt ] + * work on fixing coverity scan results: + - fix some off-by-one errors + - fix some resource leaks + - fixes in chroot() handling + - fix some missing va_end() + * make the code -Wall clean again + * remove duplicated #include + * add .travis.yml + * use the 'abi-complicance-checker' package and remove the buildin + copy for the abi checks + + [ David Kalnischkies ] + * ensure that FileFd::Size returns 0 in error cases + * add missing Turkish (tr) to po/LINGUAS + * correct management-typo in description found by lintian + * implement debian/rules build-{arch,indep} as required by policy 3.9.4 + * reenable automatic parallel build of APT + * exclude config.{sub,guess} from source package + * update the symbol files to reflect current state + * unset LANGUAGE for showing [Y/n] answer hints + * fix some unitialized data members + * specific pins below 1000 cause downgrades (Closes: 543966) + * use pkgTagFile to parse "header" of Release files + * fix: --print-uris removes authentication (Closes: 719263) + * always use our own trustdb.gpg in apt-key + * use a tmpfile for trustdb.gpg in apt-key. + Thanks to Andreas Beckmann for the initial patch! (Closes: #687611) + * do not double-slash paths in apt-key (Closes: 665411) + * make the keyring locations in apt-key configurable + * let apt-key del work better with softlink and single key keyrings + * do not call 'apt-key update' in apt.postinst + + [ Colin Watson ] + * prefer native arch over higher priority for providers (Closes: #718482) + + -- Michael Vogt Mon, 12 Aug 2013 21:45:07 +0200 apt (0.9.9.4) unstable; urgency=low -- cgit v1.2.3 From 183116d1a64a2610b88fa6b50f2c5199b69d5841 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 12 Aug 2013 23:33:57 +0200 Subject: fix typo in the test for abi-compliance-checker --- abicheck/run_abi_test | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/abicheck/run_abi_test b/abicheck/run_abi_test index 668ce8e12..9ee840ea0 100755 --- a/abicheck/run_abi_test +++ b/abicheck/run_abi_test @@ -5,8 +5,8 @@ if [ ! -d ../build ]; then exit 1 fi -if [ ! -x $(which abi-complicance-checker > /dev/null 2>&1) ]; then - echo "Please install the 'abi-complicance-checker' package" +if [ ! -x "$(which abi-compliance-checker 2>/dev/null )" ]; then + echo "Please install the 'abi-compliance-checker' package" exit 1 fi -- cgit v1.2.3 From 0e279e3527ce3dc9de0e01441ad693f415e75d6a Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 23 Apr 2013 08:15:06 +0200 Subject: merge patch from Daniel Hartwig to Clarify units of Acquire::http::Dl-Limit (closes: #705445) Conflicts: debian/changelog --- debian/changelog | 9 ++++++++- doc/apt.conf.5.xml | 10 ++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/debian/changelog b/debian/changelog index 8e4def2b0..7075cb844 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +apt (0.9.11) UNRELEASED; urgency=low + + [ Daniel Hartwig ] + * Clarify units of Acquire::http::Dl-Limit (closes: #705445) + + -- Michael Vogt Thu, 15 Aug 2013 09:27:35 +0200 + apt (0.9.10) unstable; urgency=low The "Hello to Debconf" upload @@ -38,7 +45,7 @@ apt (0.9.10) unstable; urgency=low * make the keyring locations in apt-key configurable * let apt-key del work better with softlink and single key keyrings * do not call 'apt-key update' in apt.postinst - + [ Colin Watson ] * prefer native arch over higher priority for providers (Closes: #718482) diff --git a/doc/apt.conf.5.xml b/doc/apt.conf.5.xml index 9973fe42b..f5e1f966d 100644 --- a/doc/apt.conf.5.xml +++ b/doc/apt.conf.5.xml @@ -386,10 +386,12 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";}; Acquire::http::AllowRedirect controls whether APT will follow redirects, which is enabled by default. - The used bandwidth can be limited with Acquire::http::Dl-Limit - which accepts integer values in kilobytes. The default value is 0 which deactivates - the limit and tries to use all available bandwidth (note that this option implicitly - disables downloading from multiple servers at the same time.) + The used bandwidth can be limited with + Acquire::http::Dl-Limit which accepts integer + values in kilobytes per second. The default value is 0 which + deactivates the limit and tries to use all available bandwidth. + Note that this option implicitly disables downloading from + multiple servers at the same time. Acquire::http::User-Agent can be used to set a different User-Agent for the http download method as some proxies allow access for clients -- cgit v1.2.3 From b9674b755d40b1394c397864d1fcd05ad58a88a2 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 23 Apr 2013 08:16:21 +0200 Subject: merge patch from Daniel Hartwig to Show a error message if {,dist-}upgrade is used with additional arguments (closes: #705510) --- cmdline/apt-get.cc | 6 ++++++ debian/changelog | 2 ++ 2 files changed, 8 insertions(+) diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 4b7691d93..d6a46c73e 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -1874,6 +1874,9 @@ bool DoAutomaticRemove(CacheFile &Cache) packages */ bool DoUpgrade(CommandLine &CmdL) { + if (CmdL.FileSize() != 1) + return _error->Error(_("The upgrade command takes no arguments")); + CacheFile Cache; if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false) return false; @@ -2206,6 +2209,9 @@ bool DoMarkAuto(CommandLine &CmdL) /* Intelligent upgrader that will install and remove packages at will */ bool DoDistUpgrade(CommandLine &CmdL) { + if (CmdL.FileSize() != 1) + return _error->Error(_("The dist-upgrade command takes no arguments")); + CacheFile Cache; if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false) return false; diff --git a/debian/changelog b/debian/changelog index 7075cb844..6172cb332 100644 --- a/debian/changelog +++ b/debian/changelog @@ -2,6 +2,8 @@ apt (0.9.11) UNRELEASED; urgency=low [ Daniel Hartwig ] * Clarify units of Acquire::http::Dl-Limit (closes: #705445) + * Show a error message if {,dist-}upgrade is used with additional + arguments (closes: #705510) -- Michael Vogt Thu, 15 Aug 2013 09:27:35 +0200 -- cgit v1.2.3 From d8a06f6e478323b2fa8573f6f885c0b16d403642 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Wed, 17 Oct 2012 10:29:52 +0200 Subject: * lp:~mvo/apt/config-clear: - support Configuration.Clear() for a clear of the entire configuration Conflicts: debian/changelog --- apt-pkg/contrib/configuration.cc | 12 ++++++++++++ apt-pkg/contrib/configuration.h | 1 + debian/changelog | 5 +++++ test/libapt/configuration_test.cc | 4 ++++ 4 files changed, 22 insertions(+) diff --git a/apt-pkg/contrib/configuration.cc b/apt-pkg/contrib/configuration.cc index 376617401..4ef4663c0 100644 --- a/apt-pkg/contrib/configuration.cc +++ b/apt-pkg/contrib/configuration.cc @@ -420,6 +420,18 @@ void Configuration::Clear(string const &Name, string const &Value) } } +} + /*}}}*/ +// Configuration::Clear - Clear everything /*{{{*/ +// --------------------------------------------------------------------- +void Configuration::Clear() +{ + const Configuration::Item *Top = Tree(0); + while( Top != 0 ) + { + Clear(Top->FullTag()); + Top = Top->Next; + } } /*}}}*/ // Configuration::Clear - Clear an entire tree /*{{{*/ diff --git a/apt-pkg/contrib/configuration.h b/apt-pkg/contrib/configuration.h index ea94c2fe6..8e09ea0a6 100644 --- a/apt-pkg/contrib/configuration.h +++ b/apt-pkg/contrib/configuration.h @@ -94,6 +94,7 @@ class Configuration // clear a whole tree void Clear(const std::string &Name); + void Clear(); // remove a certain value from a list (e.g. the list of "APT::Keep-Fds") void Clear(std::string const &List, std::string const &Value); diff --git a/debian/changelog b/debian/changelog index 6172cb332..1c7afd863 100644 --- a/debian/changelog +++ b/debian/changelog @@ -5,6 +5,11 @@ apt (0.9.11) UNRELEASED; urgency=low * Show a error message if {,dist-}upgrade is used with additional arguments (closes: #705510) + [ Michael Vogt ] + * lp:~mvo/apt/config-clear: + - support Configuration.Clear() for a clear of the entire + configuration + -- Michael Vogt Thu, 15 Aug 2013 09:27:35 +0200 apt (0.9.10) unstable; urgency=low diff --git a/test/libapt/configuration_test.cc b/test/libapt/configuration_test.cc index 87d5699ef..2c974ee0a 100644 --- a/test/libapt/configuration_test.cc +++ b/test/libapt/configuration_test.cc @@ -98,6 +98,10 @@ int main(int argc,const char *argv[]) { equals(Cnf.FindDir("Dir::State"), "/rootdir/dev/null"); equals(Cnf.FindDir("Dir::State::lists"), "/rootdir/dev/null"); + Cnf.Set("Moo::Bar", "1"); + Cnf.Clear(); + equals(Cnf.Find("Moo::Bar"), ""); + //FIXME: Test for configuration file parsing; // currently only integration/ tests test them implicitly -- cgit v1.2.3 From 488011fa99aee25bedb39ae2cc3115ad1ab000c0 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Wed, 17 Oct 2012 10:27:50 +0200 Subject: * lp:~mvo/apt/add-glob-function: - add Glob() to fileutl.{cc,h} Conflicts: apt-pkg/contrib/fileutl.h debian/changelog --- apt-pkg/contrib/fileutl.cc | 31 +++++++++++++++++++++++++++++++ apt-pkg/contrib/fileutl.h | 3 +++ debian/changelog | 2 ++ test/libapt/fileutl_test.cc | 42 ++++++++++++++++++++++++++++++++++++++++++ test/libapt/makefile | 5 +++++ 5 files changed, 83 insertions(+) create mode 100644 test/libapt/fileutl_test.cc diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index f24df65fc..dca468c63 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -41,6 +41,8 @@ #include #include #include +#include + #include #include @@ -1766,3 +1768,32 @@ bool FileFd::FileFdError(const char *Description,...) { /*}}}*/ gzFile FileFd::gzFd() { return (gzFile) d->gz; } + + +// Glob - wrapper around "glob()" /*{{{*/ +// --------------------------------------------------------------------- +/* */ +std::vector Glob(std::string const &pattern, int flags) +{ + std::vector result; + glob_t globbuf; + int glob_res, i; + + glob_res = glob(pattern.c_str(), flags, NULL, &globbuf); + + if (glob_res != 0) + { + if(glob_res != GLOB_NOMATCH) { + _error->Errno("glob", "Problem with glob"); + return result; + } + } + + // append results + for(i=0;i Glob(std::string const &pattern, int flags=0); + #endif diff --git a/debian/changelog b/debian/changelog index 1c7afd863..b597d1b20 100644 --- a/debian/changelog +++ b/debian/changelog @@ -9,6 +9,8 @@ apt (0.9.11) UNRELEASED; urgency=low * lp:~mvo/apt/config-clear: - support Configuration.Clear() for a clear of the entire configuration + * lp:~mvo/apt/add-glob-function: + - add Glob() to fileutl.{cc,h} -- Michael Vogt Thu, 15 Aug 2013 09:27:35 +0200 diff --git a/test/libapt/fileutl_test.cc b/test/libapt/fileutl_test.cc new file mode 100644 index 000000000..b6b8ac579 --- /dev/null +++ b/test/libapt/fileutl_test.cc @@ -0,0 +1,42 @@ +#include +#include + +#include "assert.h" +#include +#include + +#include +#include +#include + + +int main(int argc,char *argv[]) +{ + std::vector files; + + // normal match + files = Glob("*.lst"); + if (files.size() != 1) + { + _error->DumpErrors(); + return 1; + } + + // not there + files = Glob("xxxyyyzzz"); + if (files.size() != 0 || _error->PendingError()) + { + _error->DumpErrors(); + return 1; + } + + // many matches (number is a bit random) + files = Glob("*.cc"); + if (files.size() < 10) + { + _error->DumpErrors(); + return 1; + } + + return 0; +} diff --git a/test/libapt/makefile b/test/libapt/makefile index 1b67cba9d..73403b24c 100644 --- a/test/libapt/makefile +++ b/test/libapt/makefile @@ -98,6 +98,11 @@ include $(PROGRAM_H) PROGRAM = IndexCopyToSourceList${BASENAME} SLIBS = -lapt-pkg SOURCE = indexcopytosourcelist_test.cc + +# test fileutls +PROGRAM = FileUtl${BASENAME} +SLIBS = -lapt-pkg +SOURCE = fileutl_test.cc include $(PROGRAM_H) # test tagfile -- cgit v1.2.3