1########################################################################### 2# A module to handle type attributes 3# 4# Copyright (C) 2015-2018 Andrey Ponomarenko's ABI Laboratory 5# 6# Written by Andrey Ponomarenko 7# 8# This library is free software; you can redistribute it and/or 9# modify it under the terms of the GNU Lesser General Public 10# License as published by the Free Software Foundation; either 11# version 2.1 of the License, or (at your option) any later version. 12# 13# This library is distributed in the hope that it will be useful, 14# but WITHOUT ANY WARRANTY; without even the implied warranty of 15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16# Lesser General Public License for more details. 17# 18# You should have received a copy of the GNU Lesser General Public 19# License along with this library; if not, write to the Free Software 20# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 21# MA 02110-1301 USA 22########################################################################### 23use strict; 24 25my %Cache; 26 27my %TypeSpecAttributes = ( 28 "Const" => 1, 29 "Volatile" => 1, 30 "ConstVolatile" => 1, 31 "Restrict" => 1, 32 "Typedef" => 1 33); 34 35my (%TypeInfo, %TName_Tid) = (); 36 37sub initAliases_TypeAttr($) 38{ 39 my $LVer = $_[0]; 40 41 $TypeInfo{$LVer} = $In::ABI{$LVer}{"TypeInfo"}; 42 $TName_Tid{$LVer} = $In::ABI{$LVer}{"TName_Tid"}; 43} 44 45sub getTypeIdByName($$) 46{ 47 my ($TypeName, $LVer) = @_; 48 return $TName_Tid{$LVer}{formatName($TypeName, "T")}; 49} 50 51sub getShortClass($$) 52{ 53 my ($TypeId, $LVer) = @_; 54 my $TypeName = $TypeInfo{$LVer}{$TypeId}{"Name"}; 55 if($TypeInfo{$LVer}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) { 56 $TypeName = uncoverTypedefs($TypeName, $LVer); 57 } 58 if(my $NameSpace = $TypeInfo{$LVer}{$TypeId}{"NameSpace"}) { 59 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g; 60 } 61 return $TypeName; 62} 63 64sub goToFirst($$$) 65{ 66 my ($TypeId, $LVer, $Type_Type) = @_; 67 68 if(defined $Cache{"goToFirst"}{$TypeId}{$LVer}{$Type_Type}) { 69 return %{$Cache{"goToFirst"}{$TypeId}{$LVer}{$Type_Type}}; 70 } 71 if(not $TypeInfo{$LVer}{$TypeId}) { 72 return (); 73 } 74 my %Type = %{$TypeInfo{$LVer}{$TypeId}}; 75 if(not $Type{"Type"}) { 76 return (); 77 } 78 if($Type{"Type"} ne $Type_Type) 79 { 80 if(not $Type{"BaseType"}) { 81 return (); 82 } 83 %Type = goToFirst($Type{"BaseType"}, $LVer, $Type_Type); 84 } 85 $Cache{"goToFirst"}{$TypeId}{$LVer}{$Type_Type} = \%Type; 86 return %Type; 87} 88 89sub getPureType($$) 90{ 91 my ($TypeId, $LVer) = @_; 92 if(not $TypeInfo{$LVer}{$TypeId}) { 93 return (); 94 } 95 if(defined $Cache{"getPureType"}{$TypeId}{$LVer}) { 96 return %{$Cache{"getPureType"}{$TypeId}{$LVer}}; 97 } 98 my %Type = %{$TypeInfo{$LVer}{$TypeId}}; 99 if(not $Type{"BaseType"}) { 100 return %Type; 101 } 102 if($TypeSpecAttributes{$Type{"Type"}}) { 103 %Type = getPureType($Type{"BaseType"}, $LVer); 104 } 105 $Cache{"getPureType"}{$TypeId}{$LVer} = \%Type; 106 return %Type; 107} 108 109sub getPLevel($$) 110{ 111 my ($TypeId, $LVer) = @_; 112 113 if(defined $Cache{"getPLevel"}{$TypeId}{$LVer}) { 114 return $Cache{"getPLevel"}{$TypeId}{$LVer}; 115 } 116 if(not $TypeInfo{$LVer}{$TypeId}) { 117 return 0; 118 } 119 my %Type = %{$TypeInfo{$LVer}{$TypeId}}; 120 if($Type{"Type"}=~/FuncPtr|FieldPtr/) { 121 return 1; 122 } 123 my $PLevel = 0; 124 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) { 125 $PLevel += 1; 126 } 127 if(not $Type{"BaseType"}) { 128 return $PLevel; 129 } 130 $PLevel += getPLevel($Type{"BaseType"}, $LVer); 131 $Cache{"getPLevel"}{$TypeId}{$LVer} = $PLevel; 132 return $PLevel; 133} 134 135sub getBaseType($$) 136{ 137 my ($TypeId, $LVer) = @_; 138 139 if(defined $Cache{"getBaseType"}{$TypeId}{$LVer}) { 140 return %{$Cache{"getBaseType"}{$TypeId}{$LVer}}; 141 } 142 if(not $TypeInfo{$LVer}{$TypeId}) { 143 return (); 144 } 145 my %Type = %{$TypeInfo{$LVer}{$TypeId}}; 146 if(not $Type{"BaseType"}) { 147 return %Type; 148 } 149 %Type = getBaseType($Type{"BaseType"}, $LVer); 150 $Cache{"getBaseType"}{$TypeId}{$LVer} = \%Type; 151 return %Type; 152} 153 154sub getOneStepBaseType($$) 155{ 156 my ($TypeId, $LVer) = @_; 157 158 if(not $TypeInfo{$LVer}{$TypeId}) { 159 return (); 160 } 161 162 my %Type = %{$TypeInfo{$LVer}{$TypeId}}; 163 if(not $Type{"BaseType"}) { 164 return %Type; 165 } 166 if(my $BTid = $Type{"BaseType"}) 167 { 168 if($TypeInfo{$LVer}{$BTid}) { 169 return %{$TypeInfo{$LVer}{$BTid}}; 170 } 171 172 # something is going wrong 173 return (); 174 } 175 176 return %Type; 177} 178 179sub getType($$) 180{ 181 my ($TypeId, $LVer) = @_; 182 183 if(not $TypeInfo{$LVer}{$TypeId}) { 184 return (); 185 } 186 return %{$TypeInfo{$LVer}{$TypeId}}; 187} 188 189sub getBaseTypeQual($$) 190{ 191 my ($TypeId, $LVer) = @_; 192 if(not $TypeInfo{$LVer}{$TypeId}) { 193 return ""; 194 } 195 my %Type = %{$TypeInfo{$LVer}{$TypeId}}; 196 if(not $Type{"BaseType"}) { 197 return ""; 198 } 199 my $Qual = ""; 200 if($Type{"Type"} eq "Pointer") { 201 $Qual .= "*"; 202 } 203 elsif($Type{"Type"} eq "Ref") { 204 $Qual .= "&"; 205 } 206 elsif($Type{"Type"} eq "ConstVolatile") { 207 $Qual .= "const volatile"; 208 } 209 elsif($Type{"Type"} eq "Const" 210 or $Type{"Type"} eq "Volatile" 211 or $Type{"Type"} eq "Restrict") { 212 $Qual .= lc($Type{"Type"}); 213 } 214 my $BQual = getBaseTypeQual($Type{"BaseType"}, $LVer); 215 return $BQual.$Qual; 216} 217 218sub isCopyingClass($$) 219{ 220 my ($TypeId, $LVer) = @_; 221 return $TypeInfo{$LVer}{$TypeId}{"Copied"}; 222} 223 224sub getSubClasses($$$) 225{ 226 my ($ClassId, $LVer, $Recursive) = @_; 227 if(not defined $In::ABI{$LVer}{"Class_SubClasses"}{$ClassId}) { 228 return (); 229 } 230 231 my @Subs = (); 232 foreach my $SubId (keys(%{$In::ABI{$LVer}{"Class_SubClasses"}{$ClassId}})) 233 { 234 if($Recursive) 235 { 236 foreach my $SubSubId (getSubClasses($SubId, $LVer, $Recursive)) { 237 push(@Subs, $SubSubId); 238 } 239 } 240 push(@Subs, $SubId); 241 } 242 return @Subs; 243} 244 245sub getBaseClasses($$$) 246{ 247 my ($ClassId, $LVer, $Recursive) = @_; 248 my %ClassType = getType($ClassId, $LVer); 249 if(not defined $ClassType{"Base"}) { 250 return (); 251 } 252 253 my @Bases = (); 254 foreach my $BaseId (sort {$ClassType{"Base"}{$a}{"pos"}<=>$ClassType{"Base"}{$b}{"pos"}} 255 keys(%{$ClassType{"Base"}})) 256 { 257 if($Recursive) 258 { 259 foreach my $SubBaseId (getBaseClasses($BaseId, $LVer, $Recursive)) { 260 push(@Bases, $SubBaseId); 261 } 262 } 263 push(@Bases, $BaseId); 264 } 265 return @Bases; 266} 267 268return 1; 269