1########################################################################### 2# Module for ABI Compliance Checker to create ABI dumps in XML format 3# 4# Copyright (C) 2009-2011 Institute for System Programming, RAS 5# Copyright (C) 2011-2012 Nokia Corporation and/or its subsidiary(-ies) 6# Copyright (C) 2011-2012 ROSA Laboratory 7# Copyright (C) 2012-2015 Andrey Ponomarenko's ABI Laboratory 8# 9# Written by Andrey Ponomarenko 10# 11# This program is free software: you can redistribute it and/or modify 12# it under the terms of the GNU General Public License or the GNU Lesser 13# General Public License as published by the Free Software Foundation. 14# 15# This program is distributed in the hope that it will be useful, 16# but WITHOUT ANY WARRANTY; without even the implied warranty of 17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18# GNU General Public License for more details. 19# 20# You should have received a copy of the GNU General Public License 21# and the GNU Lesser General Public License along with this program. 22# If not, see <http://www.gnu.org/licenses/>. 23########################################################################### 24use strict; 25 26my $TAG_ID = 0; 27my $INDENT = " "; 28 29sub createXmlDump($) 30{ 31 my $ABI = $_[0]; 32 my $ABI_DUMP = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"; 33 34 $ABI_DUMP .= "<ABI_dump version=\"".$ABI->{"ABI_DUMP_VERSION"}."\""; 35 $ABI_DUMP .= " xml_format=\"".$ABI->{"XML_ABI_DUMP_VERSION"}."\""; 36 $ABI_DUMP .= " acc=\"".$ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"}."\">\n"; 37 38 $ABI_DUMP .= addTag("library", $ABI->{"LibraryName"}); 39 $ABI_DUMP .= addTag("library_version", $ABI->{"LibraryVersion"}); 40 $ABI_DUMP .= addTag("language", $ABI->{"Language"}); 41 42 $ABI_DUMP .= addTag("gcc", $ABI->{"GccVersion"}); 43 $ABI_DUMP .= addTag("architecture", $ABI->{"Arch"}); 44 $ABI_DUMP .= addTag("target", $ABI->{"Target"}); 45 $ABI_DUMP .= addTag("word_size", $ABI->{"WordSize"}); 46 47 if($ABI->{"Mode"}) { 48 $ABI_DUMP .= addTag("mode", $ABI->{"Mode"}); 49 } 50 if($ABI->{"SrcBin"}) { 51 $ABI_DUMP .= addTag("kind", "SrcBin"); 52 } 53 elsif($ABI->{"BinOnly"}) { 54 $ABI_DUMP .= addTag("kind", "BinOnly"); 55 } 56 57 if(my @Headers = keys(%{$ABI->{"Headers"}})) 58 { 59 @Headers = sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} @Headers; 60 $ABI_DUMP .= openTag("headers"); 61 foreach my $Name (@Headers) { 62 $ABI_DUMP .= addTag("name", $Name); 63 } 64 $ABI_DUMP .= closeTag("headers"); 65 } 66 67 if(my @NameSpaces = keys(%{$ABI->{"NameSpaces"}})) 68 { 69 $ABI_DUMP .= openTag("namespaces"); 70 foreach my $NameSpace (sort {lc($a) cmp lc($b)} @NameSpaces) { 71 $ABI_DUMP .= addTag("name", $NameSpace); 72 } 73 $ABI_DUMP .= closeTag("namespaces"); 74 } 75 76 if(my @TypeInfo = keys(%{$ABI->{"TypeInfo"}})) 77 { 78 $ABI_DUMP .= openTag("type_info"); 79 foreach my $ID (sort {$a<=>$b} @TypeInfo) 80 { 81 my %TInfo = %{$ABI->{"TypeInfo"}{$ID}}; 82 $ABI_DUMP .= openTag("data_type"); 83 $ABI_DUMP .= addTag("id", $ID); 84 foreach my $Attr ("Name", "Type", "Size", 85 "Header", "Line", "NameSpace", "Class", "Return", "Algn") 86 { 87 if(defined $TInfo{$Attr}) { 88 $ABI_DUMP .= addTag(lc($Attr), $TInfo{$Attr}); 89 } 90 } 91 if($TInfo{"Private"}) { 92 $ABI_DUMP .= addTag("access", "private"); 93 } 94 if($TInfo{"Protected"}) { 95 $ABI_DUMP .= addTag("access", "protected"); 96 } 97 if(my @Positions = keys(%{$TInfo{"Memb"}})) 98 { 99 $ABI_DUMP .= openTag("members"); 100 foreach my $Pos (sort { $a<=>$b } @Positions) 101 { 102 $ABI_DUMP .= openTag("field"); 103 $ABI_DUMP .= addTag("name", $TInfo{"Memb"}{$Pos}{"name"}); 104 if(my $MTid = $TInfo{"Memb"}{$Pos}{"type"}) { 105 $ABI_DUMP .= addTag("type", $MTid); 106 } 107 if(my $Access = $TInfo{"Memb"}{$Pos}{"access"}) { 108 $ABI_DUMP .= addTag("access", $Access); 109 } 110 my $Val = $TInfo{"Memb"}{$Pos}{"value"}; 111 if(defined $Val) { 112 $ABI_DUMP .= addTag("value", $Val); 113 } 114 if(my $Align = $TInfo{"Memb"}{$Pos}{"algn"}) { 115 $ABI_DUMP .= addTag("algn", $Align); 116 } 117 if(my $Bitfield = $TInfo{"Memb"}{$Pos}{"bitfield"}) { 118 $ABI_DUMP .= addTag("bitfield", $Bitfield); 119 } 120 if($TInfo{"Memb"}{$Pos}{"mutable"}) { 121 $ABI_DUMP .= addTag("spec", "mutable"); 122 } 123 $ABI_DUMP .= addTag("pos", $Pos); 124 $ABI_DUMP .= closeTag("field"); 125 } 126 $ABI_DUMP .= closeTag("members"); 127 } 128 if(my @Positions = keys(%{$TInfo{"Param"}})) 129 { 130 $ABI_DUMP .= openTag("parameters"); 131 foreach my $Pos (sort { $a<=>$b } @Positions) 132 { 133 $ABI_DUMP .= openTag("param"); 134 if(my $PTid = $TInfo{"Param"}{$Pos}{"type"}) { 135 $ABI_DUMP .= addTag("type", $PTid); 136 } 137 $ABI_DUMP .= addTag("pos", $Pos); 138 $ABI_DUMP .= closeTag("param"); 139 } 140 $ABI_DUMP .= closeTag("parameters"); 141 } 142 if(my @Positions = keys(%{$TInfo{"TParam"}})) 143 { 144 $ABI_DUMP .= openTag("template_parameters"); 145 foreach my $Pos (sort { $a<=>$b } @Positions) 146 { 147 $ABI_DUMP .= openTag("param"); 148 $ABI_DUMP .= addTag("name", $TInfo{"TParam"}{$Pos}{"name"}); 149 $ABI_DUMP .= addTag("pos", $Pos); 150 $ABI_DUMP .= closeTag("param"); 151 } 152 $ABI_DUMP .= closeTag("template_parameters"); 153 } 154 if(my @Offsets = keys(%{$TInfo{"VTable"}})) 155 { 156 $ABI_DUMP .= openTag("vtable"); 157 foreach my $Offset (sort { $a<=>$b } @Offsets) 158 { 159 $ABI_DUMP .= openTag("entry"); 160 $ABI_DUMP .= addTag("offset", $Offset); 161 $ABI_DUMP .= addTag("value", $TInfo{"VTable"}{$Offset}); 162 $ABI_DUMP .= closeTag("entry"); 163 } 164 $ABI_DUMP .= closeTag("vtable"); 165 } 166 if(my $BTid = $TInfo{"BaseType"}) { 167 $ABI_DUMP .= addTag("base_type", $BTid); 168 } 169 if(my @BaseIDs = keys(%{$TInfo{"Base"}})) 170 { 171 @BaseIDs = sort { $TInfo{"Base"}{$a}{"pos"}<=>$TInfo{"Base"}{$b}{"pos"} } @BaseIDs; 172 $ABI_DUMP .= openTag("base"); 173 foreach my $BaseID (@BaseIDs) 174 { 175 $ABI_DUMP .= openTag("class"); 176 $ABI_DUMP .= addTag("id", $BaseID); 177 if(my $Access = $TInfo{"Base"}{$BaseID}{"access"}) { 178 $ABI_DUMP .= addTag("access", $Access); 179 } 180 if(my $Virt = $TInfo{"Base"}{$BaseID}{"virtual"}) { 181 $ABI_DUMP .= addTag("inherit", "virtual"); 182 } 183 $ABI_DUMP .= addTag("pos", $TInfo{"Base"}{$BaseID}{"pos"}); 184 $ABI_DUMP .= closeTag("class"); 185 } 186 $ABI_DUMP .= closeTag("base"); 187 } 188 if($TInfo{"Copied"}) { 189 $ABI_DUMP .= addTag("note", "copied"); 190 } 191 if($TInfo{"Spec"}) { 192 $ABI_DUMP .= addTag("note", "specialization"); 193 } 194 if($TInfo{"Forward"}) { 195 $ABI_DUMP .= addTag("note", "forward"); 196 } 197 $ABI_DUMP .= closeTag("data_type"); 198 } 199 $ABI_DUMP .= closeTag("type_info"); 200 } 201 202 if(my @Constants = keys(%{$ABI->{"Constants"}})) 203 { 204 $ABI_DUMP .= openTag("constants"); 205 foreach my $Constant (@Constants) 206 { 207 my %CInfo = %{$ABI->{"Constants"}{$Constant}}; 208 $ABI_DUMP .= openTag("constant"); 209 $ABI_DUMP .= addTag("name", $Constant); 210 $ABI_DUMP .= addTag("value", $CInfo{"Value"}); 211 $ABI_DUMP .= addTag("header", $CInfo{"Header"}); 212 $ABI_DUMP .= closeTag("constant"); 213 } 214 $ABI_DUMP .= closeTag("constants"); 215 } 216 217 if(my @SymbolInfo = keys(%{$ABI->{"SymbolInfo"}})) 218 { 219 my %TR = ( 220 "MnglName" => "mangled", 221 "ShortName" => "short" 222 ); 223 $ABI_DUMP .= openTag("symbol_info"); 224 foreach my $ID (sort {$a<=>$b} @SymbolInfo) 225 { 226 my %SInfo = %{$ABI->{"SymbolInfo"}{$ID}}; 227 $ABI_DUMP .= openTag("symbol"); 228 $ABI_DUMP .= addTag("id", $ID); 229 foreach my $Attr ("MnglName", "ShortName", "Class", 230 "Header", "Line", "Return", "NameSpace", "Value") 231 { 232 if(defined $SInfo{$Attr}) 233 { 234 my $Tag = $Attr; 235 if($TR{$Attr}) { 236 $Tag = $TR{$Attr}; 237 } 238 $ABI_DUMP .= addTag(lc($Tag), $SInfo{$Attr}); 239 } 240 } 241 if($SInfo{"Constructor"}) { 242 $ABI_DUMP .= addTag("kind", "constructor"); 243 } 244 if($SInfo{"Destructor"}) { 245 $ABI_DUMP .= addTag("kind", "destructor"); 246 } 247 if($SInfo{"Data"}) { 248 $ABI_DUMP .= addTag("kind", "data"); 249 } 250 if($SInfo{"Virt"}) { 251 $ABI_DUMP .= addTag("spec", "virtual"); 252 } 253 elsif($SInfo{"PureVirt"}) { 254 $ABI_DUMP .= addTag("spec", "pure virtual"); 255 } 256 elsif($SInfo{"Static"}) { 257 $ABI_DUMP .= addTag("spec", "static"); 258 } 259 if($SInfo{"InLine"}) { 260 $ABI_DUMP .= addTag("spec", "inline"); 261 } 262 if($SInfo{"Const"}) { 263 $ABI_DUMP .= addTag("spec", "const"); 264 } 265 if($SInfo{"Volatile"}) { 266 $ABI_DUMP .= addTag("spec", "volatile"); 267 } 268 if($SInfo{"Private"}) { 269 $ABI_DUMP .= addTag("access", "private"); 270 } 271 if($SInfo{"Protected"}) { 272 $ABI_DUMP .= addTag("access", "protected"); 273 } 274 if($SInfo{"Artificial"}) { 275 $ABI_DUMP .= addTag("note", "artificial"); 276 } 277 if(my $Lang = $SInfo{"Lang"}) { 278 $ABI_DUMP .= addTag("lang", $Lang); 279 } 280 if(my @Positions = keys(%{$SInfo{"Param"}})) 281 { 282 $ABI_DUMP .= openTag("parameters"); 283 foreach my $Pos (sort { $a<=>$b } @Positions) 284 { 285 $ABI_DUMP .= openTag("param"); 286 if(my $PName = $SInfo{"Param"}{$Pos}{"name"}) { 287 $ABI_DUMP .= addTag("name", $PName); 288 } 289 if(my $PTid = $SInfo{"Param"}{$Pos}{"type"}) { 290 $ABI_DUMP .= addTag("type", $PTid); 291 } 292 my $Default = $SInfo{"Param"}{$Pos}{"default"}; 293 if(defined $Default) { 294 $ABI_DUMP .= addTag("default", $Default); 295 } 296 if(my $Align = $SInfo{"Param"}{$Pos}{"algn"}) { 297 $ABI_DUMP .= addTag("algn", $Align); 298 } 299 if(defined $SInfo{"Param"}{$Pos}{"reg"}) { 300 $ABI_DUMP .= addTag("call", "register"); 301 } 302 $ABI_DUMP .= addTag("pos", $Pos); 303 $ABI_DUMP .= closeTag("param"); 304 } 305 $ABI_DUMP .= closeTag("parameters"); 306 } 307 if(my @Positions = keys(%{$SInfo{"TParam"}})) 308 { 309 $ABI_DUMP .= openTag("template_parameters"); 310 foreach my $Pos (sort { $a<=>$b } @Positions) 311 { 312 $ABI_DUMP .= openTag("param"); 313 $ABI_DUMP .= addTag("name", $SInfo{"TParam"}{$Pos}{"name"}); 314 $ABI_DUMP .= closeTag("param"); 315 } 316 $ABI_DUMP .= closeTag("template_parameters"); 317 } 318 $ABI_DUMP .= closeTag("symbol"); 319 } 320 $ABI_DUMP .= closeTag("symbol_info"); 321 } 322 323 if(my @Libs = keys(%{$ABI->{"Symbols"}})) 324 { 325 $ABI_DUMP .= openTag("symbols"); 326 foreach my $Lib (sort {lc($a) cmp lc($b)} @Libs) 327 { 328 $ABI_DUMP .= openTag("library", "name", $Lib); 329 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%{$ABI->{"Symbols"}{$Lib}})) 330 { 331 if((my $Size = $ABI->{"Symbols"}{$Lib}{$Symbol})<0) 332 { # data 333 $ABI_DUMP .= addTag("symbol", $Symbol, "size", -$Size); 334 } 335 else 336 { # functions 337 $ABI_DUMP .= addTag("symbol", $Symbol); 338 } 339 } 340 $ABI_DUMP .= closeTag("library"); 341 } 342 $ABI_DUMP .= closeTag("symbols"); 343 } 344 345 if(my @DepLibs = keys(%{$ABI->{"DepSymbols"}})) 346 { 347 $ABI_DUMP .= openTag("dep_symbols"); 348 foreach my $Lib (sort {lc($a) cmp lc($b)} @DepLibs) 349 { 350 $ABI_DUMP .= openTag("library", "name", $Lib); 351 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%{$ABI->{"DepSymbols"}{$Lib}})) 352 { 353 if((my $Size = $ABI->{"DepSymbols"}{$Lib}{$Symbol})<0) 354 { # data 355 $ABI_DUMP .= addTag("symbol", $Symbol, "size", -$Size); 356 } 357 else 358 { # functions 359 $ABI_DUMP .= addTag("symbol", $Symbol); 360 } 361 } 362 $ABI_DUMP .= closeTag("library"); 363 } 364 $ABI_DUMP .= closeTag("dep_symbols"); 365 } 366 367 if(my @VSymbols = keys(%{$ABI->{"SymbolVersion"}})) 368 { 369 $ABI_DUMP .= openTag("symbol_version"); 370 foreach my $Symbol (sort {lc($a) cmp lc($b)} @VSymbols) 371 { 372 $ABI_DUMP .= openTag("symbol"); 373 $ABI_DUMP .= addTag("name", $Symbol); 374 $ABI_DUMP .= addTag("version", $ABI->{"SymbolVersion"}{$Symbol}); 375 $ABI_DUMP .= closeTag("symbol"); 376 } 377 $ABI_DUMP .= closeTag("symbol_version"); 378 } 379 380 if(my @SkipTypes = keys(%{$ABI->{"SkipTypes"}})) 381 { 382 $ABI_DUMP .= openTag("skip_types"); 383 foreach my $Name (sort {lc($a) cmp lc($b)} @SkipTypes) { 384 $ABI_DUMP .= addTag("name", $Name); 385 } 386 $ABI_DUMP .= closeTag("skip_types"); 387 } 388 389 if(my @SkipSymbols = keys(%{$ABI->{"SkipSymbols"}})) 390 { 391 $ABI_DUMP .= openTag("skip_symbols"); 392 foreach my $Name (sort {lc($a) cmp lc($b)} @SkipSymbols) { 393 $ABI_DUMP .= addTag("name", $Name); 394 } 395 $ABI_DUMP .= closeTag("skip_symbols"); 396 } 397 398 if(my @SkipNameSpaces = keys(%{$ABI->{"SkipNameSpaces"}})) 399 { 400 $ABI_DUMP .= openTag("skip_namespaces"); 401 foreach my $Name (sort {lc($a) cmp lc($b)} @SkipNameSpaces) { 402 $ABI_DUMP .= addTag("name", $Name); 403 } 404 $ABI_DUMP .= closeTag("skip_namespaces"); 405 } 406 407 if(my @SkipHeaders = keys(%{$ABI->{"SkipHeaders"}})) 408 { 409 $ABI_DUMP .= openTag("skip_headers"); 410 foreach my $Name (sort {lc($a) cmp lc($b)} @SkipHeaders) { 411 $ABI_DUMP .= addTag("name", $Name); 412 } 413 $ABI_DUMP .= closeTag("skip_headers"); 414 } 415 416 if(my @TargetHeaders = keys(%{$ABI->{"TargetHeaders"}})) 417 { 418 $ABI_DUMP .= openTag("target_headers"); 419 foreach my $Name (sort {lc($a) cmp lc($b)} @TargetHeaders) { 420 $ABI_DUMP .= addTag("name", $Name); 421 } 422 $ABI_DUMP .= closeTag("target_headers"); 423 } 424 425 $ABI_DUMP .= "</ABI_dump>\n"; 426 427 checkTags(); 428 429 return $ABI_DUMP; 430} 431 432sub readXmlDump($) 433{ 434 my $ABI_DUMP = readFile($_[0]); 435 my %ABI = {}; 436 437 $ABI{"LibraryName"} = parseTag(\$ABI_DUMP, "library"); 438 $ABI{"LibraryVersion"} = parseTag(\$ABI_DUMP, "library_version"); 439 $ABI{"Language"} = parseTag(\$ABI_DUMP, "language"); 440 $ABI{"GccVersion"} = parseTag(\$ABI_DUMP, "gcc"); 441 $ABI{"Arch"} = parseTag(\$ABI_DUMP, "architecture"); 442 $ABI{"Target"} = parseTag(\$ABI_DUMP, "target"); 443 $ABI{"WordSize"} = parseTag(\$ABI_DUMP, "word_size"); 444 445 my $Pos = 0; 446 447 if(my $Headers = parseTag(\$ABI_DUMP, "headers")) 448 { 449 while(my $Name = parseTag(\$Headers, "name")) { 450 $ABI{"Headers"}{$Name} = $Pos++; 451 } 452 } 453 454 if(my $NameSpaces = parseTag(\$ABI_DUMP, "namespaces")) 455 { 456 while(my $Name = parseTag(\$NameSpaces, "name")) { 457 $ABI{"NameSpaces"}{$Name} = 1; 458 } 459 } 460 461 if(my $TypeInfo = parseTag(\$ABI_DUMP, "type_info")) 462 { 463 while(my $DataType = parseTag(\$TypeInfo, "data_type")) 464 { 465 my %TInfo = (); 466 my $ID = parseTag(\$DataType, "id"); 467 468 if(my $Members = parseTag(\$DataType, "members")) 469 { 470 $Pos = 0; 471 while(my $Field = parseTag(\$Members, "field")) 472 { 473 my %MInfo = (); 474 $MInfo{"name"} = parseTag(\$Field, "name"); 475 if(my $Tid = parseTag(\$Field, "type")) { 476 $MInfo{"type"} = $Tid; 477 } 478 if(my $Access = parseTag(\$Field, "access")) { 479 $MInfo{"access"} = $Access; 480 } 481 my $Val = parseTag(\$Field, "value"); 482 if(defined $Val) { 483 $MInfo{"value"} = $Val; 484 } 485 if(my $Align = parseTag(\$Field, "algn")) { 486 $MInfo{"algn"} = $Align; 487 } 488 if(my $Bitfield = parseTag(\$Field, "bitfield")) { 489 $MInfo{"bitfield"} = $Bitfield; 490 } 491 if(my $Spec = parseTag(\$Field, "spec")) { 492 $MInfo{$Spec} = 1; 493 } 494 $TInfo{"Memb"}{$Pos++} = \%MInfo; 495 } 496 } 497 498 if(my $Parameters = parseTag(\$DataType, "parameters")) 499 { 500 $Pos = 0; 501 while(my $Parameter = parseTag(\$Parameters, "param")) 502 { 503 my %PInfo = (); 504 if(my $Tid = parseTag(\$Parameter, "type")) { 505 $PInfo{"type"} = $Tid; 506 } 507 $TInfo{"Param"}{$Pos++} = \%PInfo; 508 } 509 } 510 if(my $TParams = parseTag(\$DataType, "template_parameters")) 511 { 512 $Pos = 0; 513 while(my $TParam = parseTag(\$TParams, "param")) { 514 $TInfo{"TParam"}{$Pos++}{"name"} = parseTag(\$TParam, "name"); 515 } 516 } 517 if(my $VTable = parseTag(\$DataType, "vtable")) 518 { 519 $Pos = 0; 520 while(my $Entry = parseTag(\$VTable, "entry")) { 521 $TInfo{"VTable"}{parseTag(\$Entry, "offset")} = parseTag(\$Entry, "value"); 522 } 523 } 524 if(my $BTid = parseTag(\$DataType, "base_type")) { 525 $TInfo{"BaseType"} = $BTid; 526 } 527 if(my $Base = parseTag(\$DataType, "base")) 528 { 529 $Pos = 0; 530 while(my $Class = parseTag(\$Base, "class")) 531 { 532 my %CInfo = (); 533 $CInfo{"pos"} = parseTag(\$Class, "pos"); 534 if(my $Access = parseTag(\$Class, "access")) { 535 $CInfo{"access"} = $Access; 536 } 537 if(my $Inherit = parseTag(\$Class, "inherit")) 538 { 539 if($Inherit eq "virtual") { 540 $CInfo{"virtual"} = 1; 541 } 542 } 543 $TInfo{"Base"}{parseTag(\$Class, "id")} = \%CInfo; 544 } 545 } 546 while(my $Note = parseTag(\$DataType, "note")) 547 { 548 if($Note eq "copied") { 549 $TInfo{"Copied"} = 1; 550 } 551 elsif($Note eq "specialization") { 552 $TInfo{"Spec"} = 1; 553 } 554 elsif($Note eq "forward") { 555 $TInfo{"Forward"} = 1; 556 } 557 } 558 foreach my $Attr ("Name", "Type", "Size", 559 "Header", "Line", "NameSpace", "Class", "Return", "Algn") 560 { 561 my $Val = parseTag(\$DataType, lc($Attr)); 562 if(defined $Val) { 563 $TInfo{$Attr} = $Val; 564 } 565 } 566 if(my $Access = parseTag(\$DataType, "access")) { 567 $TInfo{ucfirst($Access)} = 1; 568 } 569 $ABI{"TypeInfo"}{$ID} = \%TInfo; 570 } 571 } 572 573 if(my $Constants = parseTag(\$ABI_DUMP, "constants")) 574 { 575 while(my $Constant = parseTag(\$Constants, "constant")) 576 { 577 if(my $Name = parseTag(\$Constant, "name")) 578 { 579 my %CInfo = (); 580 $CInfo{"Value"} = parseTag(\$Constant, "value"); 581 $CInfo{"Header"} = parseTag(\$Constant, "header"); 582 $ABI{"Constants"}{$Name} = \%CInfo; 583 } 584 } 585 } 586 587 if(my $SymbolInfo = parseTag(\$ABI_DUMP, "symbol_info")) 588 { 589 my %TR = ( 590 "MnglName"=>"mangled", 591 "ShortName"=>"short" 592 ); 593 while(my $Symbol = parseTag(\$SymbolInfo, "symbol")) 594 { 595 my %SInfo = (); 596 my $ID = parseTag(\$Symbol, "id"); 597 598 if(my $Parameters = parseTag(\$Symbol, "parameters")) 599 { 600 $Pos = 0; 601 while(my $Parameter = parseTag(\$Parameters, "param")) 602 { 603 my %PInfo = (); 604 if(my $PName = parseTag(\$Parameter, "name")) { 605 $PInfo{"name"} = $PName; 606 } 607 if(my $PTid = parseTag(\$Parameter, "type")) { 608 $PInfo{"type"} = $PTid; 609 } 610 my $Default = parseTag(\$Parameter, "default", "spaces"); 611 if(defined $Default) { 612 $PInfo{"default"} = $Default; 613 } 614 if(my $Align = parseTag(\$Parameter, "algn")) { 615 $PInfo{"algn"} = $Align; 616 } 617 if(my $Call = parseTag(\$Parameter, "call")) 618 { 619 if($Call eq "register") { 620 $PInfo{"reg"} = 1; 621 } 622 } 623 $SInfo{"Param"}{$Pos++} = \%PInfo; 624 } 625 } 626 if(my $TParams = parseTag(\$Symbol, "template_parameters")) 627 { 628 $Pos = 0; 629 while(my $TParam = parseTag(\$TParams, "param")) { 630 $SInfo{"TParam"}{$Pos++}{"name"} = parseTag(\$TParam, "name"); 631 } 632 } 633 634 foreach my $Attr ("MnglName", "ShortName", "Class", 635 "Header", "Line", "Return", "NameSpace", "Value") 636 { 637 my $Tag = lc($Attr); 638 if($TR{$Attr}) { 639 $Tag = $TR{$Attr}; 640 } 641 my $Val = parseTag(\$Symbol, $Tag); 642 if(defined $Val) { 643 $SInfo{$Attr} = $Val; 644 } 645 } 646 if(my $Kind = parseTag(\$Symbol, "kind")) { 647 $SInfo{ucfirst($Kind)} = 1; 648 } 649 while(my $Spec = parseTag(\$Symbol, "spec")) 650 { 651 if($Spec eq "virtual") { 652 $SInfo{"Virt"} = 1; 653 } 654 elsif($Spec eq "pure virtual") { 655 $SInfo{"PureVirt"} = 1; 656 } 657 elsif($Spec eq "inline") { 658 $SInfo{"InLine"} = 1; 659 } 660 else 661 { # const, volatile, static 662 $SInfo{ucfirst($Spec)} = 1; 663 } 664 } 665 if(my $Access = parseTag(\$Symbol, "access")) { 666 $SInfo{ucfirst($Access)} = 1; 667 } 668 if(my $Note = parseTag(\$Symbol, "note")) { 669 $SInfo{ucfirst($Note)} = 1; 670 } 671 if(my $Lang = parseTag(\$Symbol, "lang")) { 672 $SInfo{"Lang"} = $Lang; 673 } 674 $ABI{"SymbolInfo"}{$ID} = \%SInfo; 675 } 676 } 677 678 if(my $Symbols = parseTag(\$ABI_DUMP, "symbols")) 679 { 680 my %LInfo = (); 681 while(my $LibSymbols = parseTag_E(\$Symbols, "library", \%LInfo)) 682 { 683 my %SInfo = (); 684 while(my $Symbol = parseTag_E(\$LibSymbols, "symbol", \%SInfo)) 685 { 686 if(my $Size = $SInfo{"size"}) { 687 $ABI{"Symbols"}{$LInfo{"name"}}{$Symbol} = -$Size; 688 } 689 else { 690 $ABI{"Symbols"}{$LInfo{"name"}}{$Symbol} = 1; 691 } 692 %SInfo = (); 693 } 694 %LInfo = (); 695 } 696 } 697 698 if(my $DepSymbols = parseTag(\$ABI_DUMP, "dep_symbols")) 699 { 700 my %LInfo = (); 701 while(my $LibSymbols = parseTag_E(\$DepSymbols, "library", \%LInfo)) 702 { 703 my %SInfo = (); 704 while(my $Symbol = parseTag_E(\$LibSymbols, "symbol", \%SInfo)) 705 { 706 if(my $Size = $SInfo{"size"}) { 707 $ABI{"DepSymbols"}{$LInfo{"name"}}{$Symbol} = -$Size; 708 } 709 else { 710 $ABI{"DepSymbols"}{$LInfo{"name"}}{$Symbol} = 1; 711 } 712 %SInfo = (); 713 } 714 %LInfo = (); 715 } 716 } 717 718 $ABI{"SymbolVersion"} = {}; 719 720 if(my $SymbolVersion = parseTag(\$ABI_DUMP, "symbol_version")) 721 { 722 while(my $Symbol = parseTag(\$SymbolVersion, "symbol")) { 723 $ABI{"SymbolVersion"}{parseTag(\$Symbol, "name")} = parseTag(\$Symbol, "version"); 724 } 725 } 726 727 $ABI{"SkipTypes"} = {}; 728 729 if(my $SkipTypes = parseTag(\$ABI_DUMP, "skip_types")) 730 { 731 while(my $Name = parseTag(\$SkipTypes, "name")) { 732 $ABI{"SkipTypes"}{$Name} = 1; 733 } 734 } 735 736 $ABI{"SkipSymbols"} = {}; 737 738 if(my $SkipSymbols = parseTag(\$ABI_DUMP, "skip_symbols")) 739 { 740 while(my $Name = parseTag(\$SkipSymbols, "name")) { 741 $ABI{"SkipSymbols"}{$Name} = 1; 742 } 743 } 744 745 $ABI{"SkipNameSpaces"} = {}; 746 747 if(my $SkipNameSpaces = parseTag(\$ABI_DUMP, "skip_namespaces")) 748 { 749 while(my $Name = parseTag(\$SkipNameSpaces, "name")) { 750 $ABI{"SkipNameSpaces"}{$Name} = 1; 751 } 752 } 753 754 $ABI{"SkipHeaders"} = {}; 755 756 if(my $SkipHeaders = parseTag(\$ABI_DUMP, "skip_headers")) 757 { 758 while(my $Name = parseTag(\$SkipHeaders, "name")) { 759 $ABI{"SkipHeaders"}{$Name} = 1; 760 } 761 } 762 763 if(my $TargetHeaders = parseTag(\$ABI_DUMP, "target_headers")) 764 { 765 while(my $Name = parseTag(\$TargetHeaders, "name")) { 766 $ABI{"TargetHeaders"}{$Name} = 1; 767 } 768 } 769 770 if(my $Mode = parseTag(\$ABI_DUMP, "mode")) { 771 $ABI{"Mode"} = $Mode; 772 } 773 if(my $Kind = parseTag(\$ABI_DUMP, "kind")) 774 { 775 if($Kind eq "BinOnly") { 776 $ABI{"BinOnly"} = 1; 777 } 778 elsif($Kind eq "SrcBin") { 779 $ABI{"SrcBin"} = 1; 780 } 781 } 782 783 my %RInfo = (); 784 parseTag_E(\$ABI_DUMP, "ABI_dump", \%RInfo); 785 786 $ABI{"ABI_DUMP_VERSION"} = $RInfo{"version"}; 787 $ABI{"XML_ABI_DUMP_VERSION"} = $RInfo{"xml_format"}; 788 $ABI{"ABI_COMPLIANCE_CHECKER_VERSION"} = $RInfo{"acc"}; 789 790 return \%ABI; 791} 792 793sub parseTag_E($$$) 794{ 795 my ($CodeRef, $Tag, $Info) = @_; 796 if(not $Tag or not $CodeRef 797 or not $Info) { 798 return undef; 799 } 800 if(${$CodeRef}=~s/\<\Q$Tag\E(\s+([^<>]+)|)\>((.|\n)*?)\<\/\Q$Tag\E\>//) 801 { 802 my ($Ext, $Content) = ($2, $3); 803 $Content=~s/\A\s+//g; 804 $Content=~s/\s+\Z//g; 805 if($Ext) 806 { 807 while($Ext=~s/(\w+)\=\"([^\"]*)\"//) 808 { 809 my ($K, $V) = ($1, $2); 810 $Info->{$K} = xmlSpecChars_R($V); 811 } 812 } 813 if(substr($Content, 0, 1) ne "<") { 814 $Content = xmlSpecChars_R($Content); 815 } 816 return $Content; 817 } 818 return undef; 819} 820 821sub addTag(@) 822{ 823 my $Tag = shift(@_); 824 my $Val = shift(@_); 825 my @Ext = @_; 826 my $Content = openTag($Tag, @Ext); 827 chomp($Content); 828 $Content .= xmlSpecChars($Val); 829 $Content .= "</$Tag>\n"; 830 $TAG_ID-=1; 831 832 return $Content; 833} 834 835sub openTag(@) 836{ 837 my $Tag = shift(@_); 838 my @Ext = @_; 839 my $Content = ""; 840 foreach (1 .. $TAG_ID) { 841 $Content .= $INDENT; 842 } 843 $TAG_ID+=1; 844 if(@Ext) 845 { 846 $Content .= "<".$Tag; 847 my $P = 0; 848 while($P<=$#Ext-1) 849 { 850 $Content .= " ".$Ext[$P]; 851 $Content .= "=\"".xmlSpecChars($Ext[$P+1])."\""; 852 $P+=2; 853 } 854 $Content .= ">\n"; 855 } 856 else { 857 $Content .= "<".$Tag.">\n"; 858 } 859 return $Content; 860} 861 862sub closeTag($) 863{ 864 my $Tag = $_[0]; 865 my $Content = ""; 866 $TAG_ID-=1; 867 foreach (1 .. $TAG_ID) { 868 $Content .= $INDENT; 869 } 870 $Content .= "</".$Tag.">\n"; 871 return $Content; 872} 873 874sub checkTags() 875{ 876 if($TAG_ID!=0) { 877 printMsg("WARNING", "the number of opened tags is not equal to number of closed tags"); 878 } 879} 880 881return 1;