German manpage translation (Chris Leick)
[ntk/apt.git] / abicheck / abi-compliance-checker.pl
1 #!/usr/bin/perl
2 ###########################################################################
3 # ABI-compliance-checker v1.13, lightweight tool for statically checking
4 # backward binary compatibility of shared C/C++ libraries in Linux.
5 # Copyright (C) The Linux Foundation
6 # Copyright (C) Institute for System Programming, RAS
7 # Author: Andrey Ponomarenko
8 #
9 # This program is free software: you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation, either version 2 of the License, or
12 # (at your option) any later version.
13 #
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
18 #
19 # You should have received a copy of the GNU General Public License
20 # along with this program. If not, see <http://www.gnu.org/licenses/>.
21 ###########################################################################
22 use Getopt::Long;
23 Getopt::Long::Configure ("posix_default", "no_ignore_case");
24 use Data::Dumper;
25
26 my $ABI_COMPLIANCE_CHECKER_VERSION = "1.13";
27 my ($Help, $ShowVersion, %Descriptor, $TargetLibraryName, $HeaderCheckingMode_Separately, $GenerateDescriptor, $TestSystem, $DumpInfo_DescriptorPath, $CheckHeadersOnly, $InterfacesListPath, $AppPath, $ShowExpendTime);
28
29 my $CmdName = get_FileName($0);
30 GetOptions("h|help!" => \$Help,
31 "v|version!" => \$ShowVersion,
32 #general options
33 "l|library=s" => \$TargetLibraryName,
34 "d1|descriptor1=s" => \$Descriptor{1}{"Path"},
35 "d2|descriptor2=s" => \$Descriptor{2}{"Path"},
36 #extra options
37 "app|application=s" => \$AppPath,
38 "symbols_list|int_list=s" => \$InterfacesListPath,
39 "dump_abi|dump_info=s" => \$DumpInfo_DescriptorPath,
40 "headers_only!" => \$CheckHeadersOnly,
41 #other options
42 "d|descriptor_template!" => \$GenerateDescriptor,
43 "separately!" => \$HeaderCheckingMode_Separately,
44 "test!" => \$TestSystem,
45 "time!" => \$ShowExpendTime
46 ) or exit(1);
47
48 sub HELP_MESSAGE()
49 {
50 print STDERR <<"EOM"
51
52 NAME:
53 $CmdName - check ABI compatibility of shared C/C++ library versions
54
55 DESCRIPTION:
56 Lightweight tool for statically checking backward binary compatibility of shared C/C++ libraries
57 in Linux. It checks header files along with shared objects in two library versions and searches
58 for ABI changes that may lead to incompatibility. Breakage of the binary compatibility may result
59 in crashing or incorrect behavior of applications built with an old version of a library when
60 it is running with a new one.
61
62 ABI Compliance Checker was intended for library developers that are interested in ensuring
63 backward binary compatibility. Also it can be used for checking forward binary compatibility
64 and checking applications portability to the new library version.
65
66 This tool is free software: you can redistribute it and/or modify it under the terms of the GNU GPL.
67
68 USAGE:
69 $CmdName [options]
70
71 EXAMPLE OF USE:
72 $CmdName -l <library_name> -d1 <1st_version_descriptor> -d2 <2nd_version_descriptor>
73
74 GENERAL OPTIONS:
75 -h|-help
76 Print this help.
77
78 -v|-version
79 Print version.
80
81 -l|-library <name>
82 Library name (without version).
83 It affects only on the path and the title of the report.
84
85 -d1|-descriptor1 <path>
86 Path to descriptor of 1st library version.
87
88 -d2|-descriptor2 <path>
89 Path to descriptor of 2nd library version.
90
91 EXTRA OPTIONS:
92 -app|-application <path>
93 This option allow to specify the application that should be tested for portability
94 to the new library version.
95
96 -dump_abi|-dump_info <descriptor_path>
97 Dump library ABI information using specified descriptor.
98 This command will create '<library>_<ver1>.abi.tar.gz' file in the directory 'abi_dumps/<library>/'.
99 You can transfer it anywhere and pass instead of library descriptor.
100
101 -headers_only
102 Check header files without shared objects. It is easy to run, but may provide
103 a low quality ABI compliance report with false positives and without
104 detecting of added/withdrawn interfaces.
105
106 -symbols_list|-int_list <path>
107 This option allow to specify a file with a list of interfaces (mangled names in C++)
108 that should be checked, other library interfaces will not be checked.
109
110 OTHER OPTIONS:
111 -d|-descriptor_template
112 Create library descriptor template 'library-descriptor.xml' in the current directory.
113
114 -separately
115 Check headers individually. This mode requires more time for checking ABI compliance,
116 but possible compiler errors in one header can't affect others.
117
118 -test
119 Run internal tests (create two binary-incompatible versions of an artificial library
120 and run ABI-Compliance-Checker on it).
121
122 DESCRIPTOR EXAMPLE:
123 <version>
124 1.28.0
125 </version>
126
127 <headers>
128 /usr/local/atk/atk-1.28.0/include/
129 </headers>
130
131 <libs>
132 /usr/local/atk/atk-1.28.0/lib/libatk-1.0.so
133 </libs>
134
135 <include_paths>
136 /usr/include/glib-2.0/
137 /usr/lib/glib-2.0/include/
138 </include_paths>
139
140
141 Report bugs to <abi-compliance-checker\@linuxtesting.org>
142 For more information, please see: http://ispras.linux-foundation.org/index.php/ABI_compliance_checker
143 EOM
144 ;
145 }
146
147 my $Descriptor_Template = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
148 <descriptor>
149
150 <!-- Template for the library version descriptor -->
151
152 <!--
153 Necessary sections
154 -->
155
156 <version>
157 <!-- Version of the library -->
158 </version>
159
160 <headers>
161 <!-- The list of paths to header files and/or
162 directories with header files, one per line -->
163 </headers>
164
165 <libs>
166 <!-- The list of paths to shared objects and/or
167 directories with shared objects, one per line -->
168 </libs>
169
170 <!--
171 Additional sections
172 -->
173
174 <include_paths>
175 <!-- The list of paths to be searched for header files
176 needed for compiling of library headers, one per line -->
177 </include_paths>
178
179 <gcc_options>
180 <!-- Additional gcc options, one per line -->
181 </gcc_options>
182
183 <opaque_types>
184 <!-- The list of opaque types, one per line -->
185 </opaque_types>
186
187 <skip_interfaces>
188 <!-- The list of functions (mangled/symbol names in C++)
189 that should be skipped while testing, one per line -->
190 </skip_interfaces>
191
192 <include_preamble>
193 <!-- The list of header files that should be included before other headers, one per line.
194 For example, it is a tree.h for libxml2 and ft2build.h for freetype2 -->
195 </include_preamble>
196
197 </descriptor>";
198
199 my %Operator_Indication = (
200 "not" => "~",
201 "assign" => "=",
202 "andassign" => "&=",
203 "orassign" => "|=",
204 "xorassign" => "^=",
205 "or" => "|",
206 "xor" => "^",
207 "addr" => "&",
208 "and" => "&",
209 "lnot" => "!",
210 "eq" => "==",
211 "ne" => "!=",
212 "lt" => "<",
213 "lshift" => "<<",
214 "lshiftassign" => "<<=",
215 "rshiftassign" => ">>=",
216 "call" => "()",
217 "mod" => "%",
218 "modassign" => "%=",
219 "subs" => "[]",
220 "land" => "&&",
221 "lor" => "||",
222 "rshift" => ">>",
223 "ref" => "->",
224 "le" => "<=",
225 "deref" => "*",
226 "mult" => "*",
227 "preinc" => "++",
228 "delete" => " delete",
229 "vecnew" => " new[]",
230 "vecdelete" => " delete[]",
231 "predec" => "--",
232 "postinc" => "++",
233 "postdec" => "--",
234 "plusassign" => "+=",
235 "plus" => "+",
236 "minus" => "-",
237 "minusassign" => "-=",
238 "gt" => ">",
239 "ge" => ">=",
240 "new" => " new",
241 "multassign" => "*=",
242 "divassign" => "/=",
243 "div" => "/",
244 "neg" => "-",
245 "pos" => "+",
246 "memref" => "->*",
247 "compound" => ","
248 );
249
250 sub num_to_str($)
251 {
252 my $Number = $_[0];
253 if(int($Number)>3)
254 {
255 return $Number."th";
256 }
257 elsif(int($Number)==1)
258 {
259 return "1st";
260 }
261 elsif(int($Number)==2)
262 {
263 return "2nd";
264 }
265 elsif(int($Number)==3)
266 {
267 return "3rd";
268 }
269 else
270 {
271 return "";
272 }
273 }
274
275 #Global variables
276 my $REPORT_PATH;
277 my %ERR_PATH;
278 my $POINTER_SIZE;
279 my $MAX_COMMAND_LINE_ARGUMENTS = 4096;
280 my %Cache;
281 my %FuncAttr;
282 my %LibInfo;
283 my %HeaderCompileError;
284 my $StartTime;
285 my %CompilerOptions;
286 my %AddedInt;
287 my %WithdrawnInt;
288 my @RecurLib;
289 my %CheckedSoLib;
290
291 #Constants checking
292 my %ConstantsSrc;
293 my %Constants;
294
295 #Types
296 my %TypeDescr;
297 my %TemplateInstance_Func;
298 my %TemplateInstance;
299 my %OpaqueTypes;
300 my %Tid_TDid;
301 my %CheckedTypes;
302 my %Typedef_BaseName;
303 my %StdCxxTypedef;
304 my %TName_Tid;
305 my %EnumMembName_Id;
306
307 #Interfaces
308 my %FuncDescr;
309 my %ClassFunc;
310 my %ClassVirtFunc;
311 my %ClassIdVirtFunc;
312 my %ClassId;
313 my %tr_name;
314 my %mangled_name;
315 my %InternalInterfaces;
316 my %InterfacesList;
317 my %InterfacesList_App;
318 my %CheckedInterfaces;
319 my %DepInterfaces;
320
321 #Headers
322 my %Include_Preamble;
323 my %Headers;
324 my %HeaderName_Destinations;
325 my %Header_Dependency;
326
327 #Shared objects
328 my %SoLib_DefaultPath;
329
330 #Merging
331 my %CompleteSignature;
332 my @RecurTypes;
333 my %Interface_Library;
334 my %Library_Interface;
335 my %Language;
336 my %SoNames_All;
337 my $Version;
338
339 #Symbols versioning
340 my %SymVer;
341
342 #Problem descriptions
343 my %CompatProblems;
344 my %ConstantProblems;
345
346 #Rerorts
347 my $ContentID = 1;
348 my $ContentSpanStart = "<span class=\"section\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
349 my $ContentSpanEnd = "</span>\n";
350 my $ContentDivStart = "<div id=\"CONTENT_ID\" style=\"display:none;\">\n";
351 my $ContentDivEnd = "</div>\n";
352 my $Content_Counter = 0;
353
354 sub readDescriptor($)
355 {
356 my $LibVersion = $_[0];
357 if(not -e $Descriptor{$LibVersion}{"Path"})
358 {
359 return;
360 }
361 my $Descriptor_File = readFile($Descriptor{$LibVersion}{"Path"});
362 $Descriptor_File =~ s/\/\*(.|\n)+?\*\///g;
363 $Descriptor_File =~ s/<\!--(.|\n)+?-->//g;
364 if(not $Descriptor_File)
365 {
366 print "ERROR: descriptor d$LibVersion is empty\n";
367 exit(1);
368 }
369 $Descriptor{$LibVersion}{"Version"} = parseTag(\$Descriptor_File, "version");
370 if(not $Descriptor{$LibVersion}{"Version"})
371 {
372 print "ERROR: version in the descriptor d$LibVersion was not specified (section <version>)\n\n";
373 exit(1);
374 }
375 $Descriptor{$LibVersion}{"Headers"} = parseTag(\$Descriptor_File, "headers");
376 if(not $Descriptor{$LibVersion}{"Headers"})
377 {
378 print "ERROR: header files in the descriptor d$LibVersion were not specified (section <headers>)\n";
379 exit(1);
380 }
381 if(not $CheckHeadersOnly)
382 {
383 $Descriptor{$LibVersion}{"Libs"} = parseTag(\$Descriptor_File, "libs");
384 if(not $Descriptor{$LibVersion}{"Libs"})
385 {
386 print "ERROR: shared objects in the descriptor d$LibVersion were not specified (section <libs>)\n";
387 exit(1);
388 }
389 }
390 $Descriptor{$LibVersion}{"Include_Paths"} = parseTag(\$Descriptor_File, "include_paths");
391 $Descriptor{$LibVersion}{"Gcc_Options"} = parseTag(\$Descriptor_File, "gcc_options");
392 foreach my $Option (split("\n", $Descriptor{$LibVersion}{"Gcc_Options"}))
393 {
394 $Option =~ s/\A\s+|\s+\Z//g;
395 next if(not $Option);
396 $CompilerOptions{$LibVersion} .= " ".$Option;
397 }
398 $Descriptor{$LibVersion}{"Opaque_Types"} = parseTag(\$Descriptor_File, "opaque_types");
399 foreach my $Type_Name (split("\n", $Descriptor{$LibVersion}{"Opaque_Types"}))
400 {
401 $Type_Name =~ s/\A\s+|\s+\Z//g;
402 next if(not $Type_Name);
403 $OpaqueTypes{$LibVersion}{$Type_Name} = 1;
404 }
405 $Descriptor{$LibVersion}{"Skip_interfaces"} = parseTag(\$Descriptor_File, "skip_interfaces");
406 foreach my $Interface_Name (split("\n", $Descriptor{$LibVersion}{"Skip_interfaces"}))
407 {
408 $Interface_Name =~ s/\A\s+|\s+\Z//g;
409 next if(not $Interface_Name);
410 $InternalInterfaces{$LibVersion}{$Interface_Name} = 1;
411 }
412 $Descriptor{$LibVersion}{"Include_Preamble"} = parseTag(\$Descriptor_File, "include_preamble");
413 my $Position = 0;
414 foreach my $Header_Name (split("\n", $Descriptor{$LibVersion}{"Include_Preamble"}))
415 {
416 $Header_Name =~ s/\A\s+|\s+\Z//g;
417 next if(not $Header_Name);
418 $Include_Preamble{$LibVersion}{$Header_Name}{"Position"} = $Position;
419 $Position+=1;
420 }
421 my $Descriptors_Dir = "descriptors_storage/$TargetLibraryName";
422 system("mkdir", "-p", $Descriptors_Dir);
423 my $Descriptor_Name = $TargetLibraryName."_".$Descriptor{$LibVersion}{"Version"}.".desc";
424 if($Descriptor{$LibVersion}{"Path"} ne $Descriptors_Dir."/".$Descriptor_Name)
425 {
426 system("cp", "-f", $Descriptor{$LibVersion}{"Path"}, $Descriptors_Dir."/".$Descriptor_Name);
427 }
428 $ERR_PATH{$LibVersion} = "header_compile_errors/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
429 }
430
431 sub parseTag($$)
432 {
433 my ($CodeRef, $Tag) = @_;
434 return "" if(not $CodeRef or not ${$CodeRef} or not $Tag);
435 if(${$CodeRef} =~ s/\<$Tag\>((.|\n)+?)\<\/$Tag\>//)
436 {
437 my $Content = $1;
438 $Content=~s/(\A\s+|\s+\Z)//g;
439 return $Content;
440 }
441 else
442 {
443 return "";
444 }
445 }
446
447 my %check_node=(
448 "array_type"=>1,
449 "binfo"=>1,
450 "boolean_type"=>1,
451 "complex_type"=>1,
452 "const_decl"=>1,
453 "enumeral_type"=>1,
454 "field_decl"=>1,
455 "function_decl"=>1,
456 "function_type"=>1,
457 "identifier_node"=>1,
458 "integer_cst"=>1,
459 "integer_type"=>1,
460 "method_type"=>1,
461 "namespace_decl"=>1,
462 "parm_decl"=>1,
463 "pointer_type"=>1,
464 "real_cst"=>1,
465 "real_type"=>1,
466 "record_type"=>1,
467 "reference_type"=>1,
468 "string_cst"=>1,
469 "template_decl"=>1,
470 "template_type_parm"=>1,
471 "tree_list"=>1,
472 "tree_vec"=>1,
473 "type_decl"=>1,
474 "union_type"=>1,
475 "var_decl"=>1,
476 "void_type"=>1);
477
478 sub getInfo($)
479 {
480 my $InfoPath = $_[0];
481 return if(not $InfoPath or not -f $InfoPath);
482 my $InfoPath_New = $InfoPath.".1";
483 #my $Keywords = join("\\|", keys(%check_node));#|grep "$Keywords"
484 system("sed ':a;N;\$!ba;s/\\n[^\@]//g' ".esc($InfoPath)."|sed 's/ [ ]\\+/ /g' > ".esc($InfoPath_New));
485 system("rm", "-fr", $InfoPath);
486 #getting info
487 open(INFO, $InfoPath_New) || die ("can't open file '\$InfoPath_New\': $!\n");
488 while(<INFO>)
489 {
490 chomp;
491 if(/\A@([0-9]+)[ ]+([a-zA-Z_]+)[ ]+(.*)\Z/)
492 {
493 next if(not $check_node{$2});
494 $LibInfo{$Version}{$1}{"info_type"}=$2;
495 $LibInfo{$Version}{$1}{"info"}=$3;
496 }
497 }
498 close(INFO);
499 system("rm", "-fr", $InfoPath_New);
500 #processing info
501 setTemplateParams_All();
502 getTypeDescr_All();
503 getFuncDescr_All();
504 getVarDescr_All();
505 %LibInfo = ();
506 %TemplateInstance = ();
507 }
508
509 sub setTemplateParams_All()
510 {
511 foreach (keys(%{$LibInfo{$Version}}))
512 {
513 if($LibInfo{$Version}{$_}{"info_type"} eq "template_decl")
514 {
515 setTemplateParams($_);
516 }
517 }
518 }
519
520 sub setTemplateParams($)
521 {
522 my $TypeInfoId = $_[0];
523 my $Info = $LibInfo{$Version}{$TypeInfoId}{"info"};
524 if($Info =~ /(inst|spcs)[ ]*:[ ]*@([0-9]+) /)
525 {
526 my $TmplInst_InfoId = $2;
527 setTemplateInstParams($TmplInst_InfoId);
528 my $TmplInst_Info = $LibInfo{$Version}{$TmplInst_InfoId}{"info"};
529 while($TmplInst_Info =~ /chan[ ]*:[ ]*@([0-9]+) /)
530 {
531 $TmplInst_InfoId = $1;
532 $TmplInst_Info = $LibInfo{$Version}{$TmplInst_InfoId}{"info"};
533 setTemplateInstParams($TmplInst_InfoId);
534 }
535 }
536 }
537
538 sub setTemplateInstParams($)
539 {
540 my $TmplInst_Id = $_[0];
541 my $Info = $LibInfo{$Version}{$TmplInst_Id}{"info"};
542 my ($Params_InfoId, $ElemId) = ();
543 if($Info =~ /purp[ ]*:[ ]*@([0-9]+) /)
544 {
545 $Params_InfoId = $1;
546 }
547 if($Info =~ /valu[ ]*:[ ]*@([0-9]+) /)
548 {
549 $ElemId = $1;
550 }
551 if($Params_InfoId and $ElemId)
552 {
553 my $Params_Info = $LibInfo{$Version}{$Params_InfoId}{"info"};
554 while($Params_Info =~ s/ ([0-9]+)[ ]*:[ ]*@([0-9]+) //)
555 {
556 my ($Param_Pos, $Param_TypeId) = ($1, $2);
557 return if($LibInfo{$Version}{$Param_TypeId}{"info_type"} eq "template_type_parm");
558 if($LibInfo{$ElemId}{"info_type"} eq "function_decl")
559 {
560 $TemplateInstance_Func{$Version}{$ElemId}{$Param_Pos} = $Param_TypeId;
561 }
562 else
563 {
564 $TemplateInstance{$Version}{getTypeDeclId($ElemId)}{$ElemId}{$Param_Pos} = $Param_TypeId;
565 }
566 }
567 }
568 }
569
570 sub getTypeDeclId($)
571 {
572 my $TypeInfo = $LibInfo{$Version}{$_[0]}{"info"};
573 if($TypeInfo =~ /name[ ]*:[ ]*@([0-9]+)/)
574 {
575 return $1;
576 }
577 else
578 {
579 return "";
580 }
581 }
582
583 sub isFuncPtr($)
584 {
585 my $Ptd = pointTo($_[0]);
586 if($Ptd)
587 {
588 if(($LibInfo{$Version}{$_[0]}{"info"} =~ m/unql[ ]*:/) and not ($LibInfo{$Version}{$_[0]}{"info"} =~ m/qual[ ]*:/))
589 {
590 return 0;
591 }
592 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"))
593 {
594 return 1;
595 }
596 else
597 {
598 return 0;
599 }
600 }
601 else
602 {
603 return 0;
604 }
605 }
606
607 sub pointTo($)
608 {
609 my $TypeInfo = $LibInfo{$Version}{$_[0]}{"info"};
610 if($TypeInfo =~ /ptd[ ]*:[ ]*@([0-9]+)/)
611 {
612 return $1;
613 }
614 else
615 {
616 return "";
617 }
618 }
619
620 sub getTypeDescr_All()
621 {
622 foreach (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}}))
623 {
624 if($LibInfo{$Version}{$_}{"info_type"}=~/_type\Z/ and $LibInfo{$Version}{$_}{"info_type"}!~/function_type|method_type/)
625 {
626 getTypeDescr(getTypeDeclId($_), $_);
627 }
628 }
629 $TypeDescr{$Version}{""}{-1}{"Name"} = "...";
630 $TypeDescr{$Version}{""}{-1}{"Type"} = "Intrinsic";
631 $TypeDescr{$Version}{""}{-1}{"Tid"} = -1;
632 }
633
634 sub getTypeDescr($$)
635 {
636 my ($TypeDeclId, $TypeId) = @_;
637 $Tid_TDid{$Version}{$TypeId} = $TypeDeclId;
638 %{$TypeDescr{$Version}{$TypeDeclId}{$TypeId}} = getTypeAttr($TypeDeclId, $TypeId);
639 if(not $TypeDescr{$Version}{$TypeDeclId}{$TypeId}{"Name"})
640 {
641 delete($TypeDescr{$Version}{$TypeDeclId}{$TypeId});
642 return;
643 }
644 if(not $TName_Tid{$Version}{$TypeDescr{$Version}{$TypeDeclId}{$TypeId}{"Name"}})
645 {
646 $TName_Tid{$Version}{$TypeDescr{$Version}{$TypeDeclId}{$TypeId}{"Name"}} = $TypeId;
647 }
648 }
649
650 sub getTypeAttr($$)
651 {
652 my ($TypeDeclId, $TypeId) = @_;
653 my ($BaseTypeSpec, %TypeAttr) = ();
654 if($TypeDescr{$Version}{$TypeDeclId}{$TypeId}{"Name"})
655 {
656 return %{$TypeDescr{$Version}{$TypeDeclId}{$TypeId}};
657 }
658 $TypeAttr{"Tid"} = $TypeId;
659 $TypeAttr{"TDid"} = $TypeDeclId;
660 $TypeAttr{"Type"} = getTypeType($TypeDeclId, $TypeId);
661 if($TypeAttr{"Type"} eq "Unknown")
662 {
663 return ();
664 }
665 elsif($TypeAttr{"Type"} eq "FuncPtr")
666 {
667 %{$TypeDescr{$Version}{$TypeDeclId}{$TypeId}} = getFuncPtrAttr(pointTo($TypeId), $TypeDeclId, $TypeId);
668 $TName_Tid{$Version}{$TypeDescr{$Version}{$TypeDeclId}{$TypeId}{"Name"}} = $TypeId;
669 return %{$TypeDescr{$Version}{$TypeDeclId}{$TypeId}};
670 }
671 elsif($TypeAttr{"Type"} eq "Array")
672 {
673 ($TypeAttr{"BaseType"}{"Tid"}, $TypeAttr{"BaseType"}{"TDid"}, $BaseTypeSpec) = selectBaseType($TypeDeclId, $TypeId);
674 my %BaseTypeAttr = getTypeAttr($TypeAttr{"BaseType"}{"TDid"}, $TypeAttr{"BaseType"}{"Tid"});
675 my $ArrayElemNum = getSize($TypeId)/8;
676 $ArrayElemNum = $ArrayElemNum/$BaseTypeAttr{"Size"} if($BaseTypeAttr{"Size"});
677 $TypeAttr{"Size"} = $ArrayElemNum;
678 if($ArrayElemNum)
679 {
680 $TypeAttr{"Name"} = $BaseTypeAttr{"Name"}."[".$ArrayElemNum."]";
681 }
682 else
683 {
684 $TypeAttr{"Name"} = $BaseTypeAttr{"Name"}."[]";
685 }
686 $TypeAttr{"Name"} = correctName($TypeAttr{"Name"});
687 $TypeAttr{"Library"} = $BaseTypeAttr{"Library"};
688 $TypeAttr{"Header"} = $BaseTypeAttr{"Header"};
689 %{$TypeDescr{$Version}{$TypeDeclId}{$TypeId}} = %TypeAttr;
690 $TName_Tid{$Version}{$TypeDescr{$Version}{$TypeDeclId}{$TypeId}{"Name"}} = $TypeId;
691 return %TypeAttr;
692 }
693 elsif($TypeAttr{"Type"} =~ /Intrinsic|Union|Struct|Enum|Class/)
694 {
695 if($TemplateInstance{$Version}{$TypeDeclId}{$TypeId})
696 {
697 my @Template_Params = ();
698 foreach my $Param_Pos (sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$TypeDeclId}{$TypeId}}))
699 {
700 my $Type_Id = $TemplateInstance{$Version}{$TypeDeclId}{$TypeId}{$Param_Pos};
701 my $Param = get_TemplateParam($Type_Id);
702 if($Param eq "")
703 {
704 return ();
705 }
706 @Template_Params = (@Template_Params, $Param);
707 }
708 %{$TypeDescr{$Version}{$TypeDeclId}{$TypeId}} = getTrivialTypeAttr($TypeDeclId, $TypeId);
709 $TypeDescr{$Version}{$TypeDeclId}{$TypeId}{"Name"} = $TypeDescr{$Version}{$TypeDeclId}{$TypeId}{"Name"}."< ".join(", ", @Template_Params)." >";
710 $TypeDescr{$Version}{$TypeDeclId}{$TypeId}{"Name"} = correctName($TypeDescr{$Version}{$TypeDeclId}{$TypeId}{"Name"});
711 $TName_Tid{$Version}{$TypeDescr{$Version}{$TypeDeclId}{$TypeId}{"Name"}} = $TypeId;
712 return %{$TypeDescr{$Version}{$TypeDeclId}{$TypeId}};
713 }
714 else
715 {
716 %{$TypeDescr{$Version}{$TypeDeclId}{$TypeId}} = getTrivialTypeAttr($TypeDeclId, $TypeId);
717 return %{$TypeDescr{$Version}{$TypeDeclId}{$TypeId}};
718 }
719 }
720 else
721 {
722 ($TypeAttr{"BaseType"}{"Tid"}, $TypeAttr{"BaseType"}{"TDid"}, $BaseTypeSpec) = selectBaseType($TypeDeclId, $TypeId);
723 my %BaseTypeAttr = getTypeAttr($TypeAttr{"BaseType"}{"TDid"}, $TypeAttr{"BaseType"}{"Tid"});
724 if($BaseTypeSpec and $BaseTypeAttr{"Name"})
725 {
726 if(($TypeAttr{"Type"} eq "Pointer") and $BaseTypeAttr{"Name"}=~/\([\*]+\)/)
727 {
728 $TypeAttr{"Name"} = $BaseTypeAttr{"Name"};
729 $TypeAttr{"Name"} =~ s/\(([*]+)\)/($1*)/g;
730 }
731 else
732 {
733 $TypeAttr{"Name"} = $BaseTypeAttr{"Name"}." ".$BaseTypeSpec;
734 }
735 }
736 elsif($BaseTypeAttr{"Name"})
737 {
738 $TypeAttr{"Name"} = $BaseTypeAttr{"Name"};
739 }
740 if($TypeAttr{"Type"} eq "Typedef")
741 {
742 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId);
743 $TypeAttr{"NameSpace"} = getNameSpace($TypeDeclId);
744 if($TypeAttr{"NameSpace"})
745 {
746 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
747 }
748 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId);
749 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BaseTypeAttr{"NameSpace"}=~/\Astd(::|\Z)/)
750 {
751 $StdCxxTypedef{$Version}{$BaseTypeAttr{"Name"}} = $TypeAttr{"Name"};
752 }
753 $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BaseTypeAttr{"Name"};
754 }
755 if(not $TypeAttr{"Size"})
756 {
757 if($TypeAttr{"Type"} eq "Pointer")
758 {
759 $TypeAttr{"Size"} = $POINTER_SIZE;
760 }
761 else
762 {
763 $TypeAttr{"Size"} = $BaseTypeAttr{"Size"};
764 }
765 }
766 $TypeAttr{"Name"} = correctName($TypeAttr{"Name"});
767 $TypeAttr{"Library"} = $BaseTypeAttr{"Library"};
768 $TypeAttr{"Header"} = $BaseTypeAttr{"Header"} if(not $TypeAttr{"Header"});
769 %{$TypeDescr{$Version}{$TypeDeclId}{$TypeId}} = %TypeAttr;
770 $TName_Tid{$Version}{$TypeDescr{$Version}{$TypeDeclId}{$TypeId}{"Name"}} = $TypeId;
771 return %TypeAttr;
772 }
773 }
774
775 sub get_TemplateParam($)
776 {
777 my $Type_Id = $_[0];
778 if(getNodeType($Type_Id) eq "integer_cst")
779 {
780 return getNodeIntCst($Type_Id);
781 }
782 elsif(getNodeType($Type_Id) eq "string_cst")
783 {
784 return getNodeStrCst($Type_Id);
785 }
786 else
787 {
788 my $Type_DId = getTypeDeclId($Type_Id);
789 my %ParamAttr = getTypeAttr($Type_DId, $Type_Id);
790 if(not $ParamAttr{"Name"})
791 {
792 return "";
793 }
794 if($ParamAttr{"Name"}=~/\>/)
795 {
796 if($StdCxxTypedef{$Version}{$ParamAttr{"Name"}})
797 {
798 return $StdCxxTypedef{$Version}{$ParamAttr{"Name"}};
799 }
800 elsif(my $Covered = cover_stdcxx_typedef($ParamAttr{"Name"}))
801 {
802 return $Covered;
803 }
804 else
805 {
806 return $ParamAttr{"Name"};
807 }
808 }
809 else
810 {
811 return $ParamAttr{"Name"};
812 }
813 }
814 }
815
816 sub cover_stdcxx_typedef($)
817 {
818 my $TypeName = $_[0];
819 my $TypeName_Covered = $TypeName;
820 while($TypeName=~s/>[ ]*(const|volatile|restrict| |\*|\&)\Z/>/g){};
821 if(my $Cover = $StdCxxTypedef{$Version}{$TypeName})
822 {
823 $TypeName = esc_l($TypeName);
824 $TypeName_Covered=~s/$TypeName/$Cover /g;
825 }
826 return correctName($TypeName_Covered);
827 }
828
829 sub getNodeType($)
830 {
831 return $LibInfo{$Version}{$_[0]}{"info_type"};
832 }
833
834 sub getNodeIntCst($)
835 {
836 my $CstId = $_[0];
837 my $CstTypeId = getTreeAttr($CstId, "type");
838 if($EnumMembName_Id{$Version}{$CstId})
839 {
840 return $EnumMembName_Id{$Version}{$CstId};
841 }
842 elsif($LibInfo{$Version}{$_[0]}{"info"} =~ /low[ ]*:[ ]*([^ ]+) /)
843 {
844 if($1 eq "0")
845 {
846 if(getNodeType($CstTypeId) eq "boolean_type")
847 {
848 return "false";
849 }
850 else
851 {
852 return "0";
853 }
854 }
855 elsif($1 eq "1")
856 {
857 if(getNodeType($CstTypeId) eq "boolean_type")
858 {
859 return "true";
860 }
861 else
862 {
863 return "1";
864 }
865 }
866 else
867 {
868 return $1;
869 }
870 }
871 else
872 {
873 return "";
874 }
875 }
876
877 sub getNodeStrCst($)
878 {
879 if($LibInfo{$Version}{$_[0]}{"info"} =~ /low[ ]*:[ ]*(.+)[ ]+lngt/)
880 {
881 return $1;
882 }
883 else
884 {
885 return "";
886 }
887 }
888
889 sub esc_l($)
890 {
891 my $String = $_[0];
892 $String=~s/([()*])/\\$1/g;
893 return $String;
894 }
895
896 sub getFuncPtrAttr($$$)
897 {
898 my ($FuncTypeId, $TypeDeclId, $TypeId) = @_;
899 my $FuncInfo = $LibInfo{$Version}{$FuncTypeId}{"info"};
900 my $FuncInfo_Type = $LibInfo{$Version}{$FuncTypeId}{"info_type"};
901 my $FuncPtrCorrectName = "";
902 my %TypeAttr = ("Size"=>$POINTER_SIZE, "Type"=>"FuncPtr", "TDid"=>$TypeDeclId, "Tid"=>$TypeId);
903 my @ParamTypeName;
904 if($FuncInfo =~ /retn[ ]*:[ ]*\@([0-9]+) /)
905 {
906 my $ReturnTypeId = $1;
907 my %ReturnAttr = getTypeAttr(getTypeDeclId($ReturnTypeId), $ReturnTypeId);
908 $FuncPtrCorrectName .= $ReturnAttr{"Name"};
909 $TypeAttr{"Return"} = $ReturnTypeId;
910 }
911 if($FuncInfo =~ /prms[ ]*:[ ]*@([0-9]+) /)
912 {
913 my $ParamTypeInfoId = $1;
914 my $Position = 0;
915 while($ParamTypeInfoId)
916 {
917 my $ParamTypeInfo = $LibInfo{$Version}{$ParamTypeInfoId}{"info"};
918 last if($ParamTypeInfo !~ /valu[ ]*:[ ]*@([0-9]+) /);
919 my $ParamTypeId = $1;
920 my %ParamAttr = getTypeAttr(getTypeDeclId($ParamTypeId), $ParamTypeId);
921 last if($ParamAttr{"Name"} eq "void");
922 $TypeAttr{"Memb"}{$Position}{"type"} = $ParamTypeId;
923 push(@ParamTypeName, $ParamAttr{"Name"});
924 last if($ParamTypeInfo !~ /chan[ ]*:[ ]*@([0-9]+) /);
925 $ParamTypeInfoId = $1;
926 $Position+=1;
927 }
928 }
929 if($FuncInfo_Type eq "function_type")
930 {
931 $FuncPtrCorrectName .= " (*) (".join(", ", @ParamTypeName).")";
932 }
933 elsif($FuncInfo_Type eq "method_type")
934 {
935 if($FuncInfo =~ /clas[ ]*:[ ]*@([0-9]+) /)
936 {
937 my $ClassId = $1;
938 my $ClassName = $TypeDescr{$Version}{getTypeDeclId($ClassId)}{$ClassId}{"Name"};
939 if($ClassName)
940 {
941 $FuncPtrCorrectName .= " ($ClassName\:\:*) (".join(", ", @ParamTypeName).")";
942 }
943 else
944 {
945 $FuncPtrCorrectName .= " (*) (".join(", ", @ParamTypeName).")";
946 }
947 }
948 else
949 {
950 $FuncPtrCorrectName .= " (*) (".join(", ", @ParamTypeName).")";
951 }
952 }
953 $TypeAttr{"Name"} = correctName($FuncPtrCorrectName);
954 return %TypeAttr;
955 }
956
957 sub getTypeName($)
958 {
959 my $Info = $LibInfo{$Version}{$_[0]}{"info"};
960 if($Info =~ /name[ ]*:[ ]*@([0-9]+) /)
961 {
962 return getNameByInfo($1);
963 }
964 else
965 {
966 if($LibInfo{$Version}{$_[0]}{"info_type"} eq "integer_type")
967 {
968 if($LibInfo{$Version}{$_[0]}{"info"} =~ /unsigned/)
969 {
970 return "unsigned int";
971 }
972 else
973 {
974 return "int";
975 }
976 }
977 else
978 {
979 return "";
980 }
981 }
982 }
983
984 sub selectBaseType($$)
985 {
986 my ($TypeDeclId, $TypeId) = @_;
987 my $TypeInfo = $LibInfo{$Version}{$TypeId}{"info"};
988 my $BaseTypeDeclId;
989 my $Type_Type = getTypeType($TypeDeclId, $TypeId);
990 #qualifications
991 if(($LibInfo{$Version}{$TypeId}{"info"} =~ /qual[ ]*:[ ]*c /) and ($LibInfo{$Version}{$TypeId}{"info"} =~ /unql[ ]*:[ ]*\@([0-9]+) /))
992 {
993 return ($1, getTypeDeclId($1), "const");
994 }
995 elsif(($LibInfo{$Version}{$TypeId}{"info"} =~ /qual[ ]*:[ ]*r /) and ($LibInfo{$Version}{$TypeId}{"info"} =~ /unql[ ]*:[ ]*\@([0-9]+) /))
996 {
997 return ($1, getTypeDeclId($1), "restrict");
998 }
999 elsif(($LibInfo{$Version}{$TypeId}{"info"} =~ /qual[ ]*:[ ]*v /) and ($LibInfo{$Version}{$TypeId}{"info"} =~ /unql[ ]*:[ ]*\@([0-9]+) /))
1000 {
1001 return ($1, getTypeDeclId($1), "volatile");
1002 }
1003 elsif((not ($LibInfo{$Version}{$TypeId}{"info"} =~ /qual[ ]*:/)) and ($LibInfo{$Version}{$TypeId}{"info"} =~ /unql[ ]*:[ ]*\@([0-9]+) /))
1004 {#typedefs
1005 return ($1, getTypeDeclId($1), "");
1006 }
1007 elsif($LibInfo{$Version}{$TypeId}{"info_type"} eq "reference_type")
1008 {
1009 if($TypeInfo =~ /refd[ ]*:[ ]*@([0-9]+) /)
1010 {
1011 return ($1, getTypeDeclId($1), "&");
1012 }
1013 else
1014 {
1015 return (0, 0, "");
1016 }
1017 }
1018 elsif($LibInfo{$Version}{$TypeId}{"info_type"} eq "array_type")
1019 {
1020 if($TypeInfo =~ /elts[ ]*:[ ]*@([0-9]+) /)
1021 {
1022 return ($1, getTypeDeclId($1), "");
1023 }
1024 else
1025 {
1026 return (0, 0, "");
1027 }
1028 }
1029 elsif($LibInfo{$Version}{$TypeId}{"info_type"} eq "pointer_type")
1030 {
1031 if($TypeInfo =~ /ptd[ ]*:[ ]*@([0-9]+) /)
1032 {
1033 return ($1, getTypeDeclId($1), "*");
1034 }
1035 else
1036 {
1037 return (0, 0, "");
1038 }
1039 }
1040 else
1041 {
1042 return (0, 0, "");
1043 }
1044 }
1045
1046 sub getFuncDescr_All()
1047 {
1048 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}}))
1049 {
1050 if($LibInfo{$Version}{$_}{"info_type"} eq "function_decl")
1051 {
1052 getFuncDescr($_);
1053 }
1054 }
1055 }
1056
1057 sub getVarDescr_All()
1058 {
1059 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}}))
1060 {
1061 if($LibInfo{$Version}{$_}{"info_type"} eq "var_decl")
1062 {
1063 getVarDescr($_);
1064 }
1065 }
1066 }
1067
1068 sub getVarDescr($)
1069 {
1070 my $FuncInfoId = $_[0];
1071 if($LibInfo{$Version}{getNameSpaceId($FuncInfoId)}{"info_type"} eq "function_decl")
1072 {
1073 return;
1074 }
1075 ($FuncDescr{$Version}{$FuncInfoId}{"Header"}, $FuncDescr{$Version}{$FuncInfoId}{"Line"}) = getLocation($FuncInfoId);
1076 if((not $FuncDescr{$Version}{$FuncInfoId}{"Header"}) or ($FuncDescr{$Version}{$FuncInfoId}{"Header"}=~/\<built\-in\>|\<internal\>/))
1077 {
1078 delete($FuncDescr{$Version}{$FuncInfoId});
1079 return;
1080 }
1081 $FuncDescr{$Version}{$FuncInfoId}{"ShortName"} = getNameByInfo($FuncInfoId);
1082 $FuncDescr{$Version}{$FuncInfoId}{"MnglName"} = getFuncMnglName($FuncInfoId);
1083 if($FuncDescr{$Version}{$FuncInfoId}{"MnglName"} and $FuncDescr{$Version}{$FuncInfoId}{"MnglName"}!~/\A_Z/)
1084 {
1085 delete($FuncDescr{$Version}{$FuncInfoId});
1086 return;
1087 }
1088 if(not $FuncDescr{$Version}{$FuncInfoId}{"MnglName"})
1089 {
1090 $FuncDescr{$Version}{$FuncInfoId}{"Name"} = $FuncDescr{$Version}{$FuncInfoId}{"ShortName"};
1091 $FuncDescr{$Version}{$FuncInfoId}{"MnglName"} = $FuncDescr{$Version}{$FuncInfoId}{"ShortName"};
1092 }
1093 if(not is_in_library($FuncDescr{$Version}{$FuncInfoId}{"MnglName"}, $Version) and not $CheckHeadersOnly)
1094 {
1095 delete $FuncDescr{$Version}{$FuncInfoId};
1096 return;
1097 }
1098 $FuncDescr{$Version}{$FuncInfoId}{"Return"} = getTypeId($FuncInfoId);
1099 delete($FuncDescr{$Version}{$FuncInfoId}{"Return"}) if(not $FuncDescr{$Version}{$FuncInfoId}{"Return"});
1100 $FuncDescr{$Version}{$FuncInfoId}{"Data"} = 1;
1101 set_Class_And_Namespace($FuncInfoId);
1102 setFuncAccess($FuncInfoId);
1103 if($FuncDescr{$Version}{$FuncInfoId}{"MnglName"} =~ /\A_ZTV/)
1104 {
1105 delete($FuncDescr{$Version}{$FuncInfoId}{"Return"});
1106 }
1107 if($FuncDescr{$Version}{$FuncInfoId}{"ShortName"} =~ /\A_Z/)
1108 {
1109 delete($FuncDescr{$Version}{$FuncInfoId}{"ShortName"});
1110 }
1111 }
1112
1113 sub getTrivialTypeAttr($$)
1114 {
1115 my ($TypeInfoId, $TypeId) = @_;
1116 my %TypeAttr = ();
1117 return if(getTypeTypeByTypeId($TypeId)!~/Intrinsic|Union|Struct|Enum/);
1118 setTypeAccess($TypeId, \%TypeAttr);
1119 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
1120 if(($TypeAttr{"Header"} eq "<built-in>") or ($TypeAttr{"Header"} eq "<internal>"))
1121 {
1122 delete($TypeAttr{"Header"});
1123 }
1124 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId);
1125 $TypeAttr{"Name"} = getTypeName($TypeId) if(not $TypeAttr{"Name"});
1126 my $NameSpaceId = getNameSpaceId($TypeInfoId);
1127 if($NameSpaceId ne $TypeId)
1128 {
1129 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId);
1130 }
1131 if($TypeAttr{"NameSpace"} and isNotAnon($TypeAttr{"Name"}))
1132 {
1133 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
1134 }
1135 $TypeAttr{"Name"} = correctName($TypeAttr{"Name"});
1136 if(isAnon($TypeAttr{"Name"}))
1137 {
1138 $TypeAttr{"Name"} = "anon-";
1139 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"};
1140 }
1141 $TypeAttr{"Size"} = getSize($TypeId)/8;
1142 $TypeAttr{"Type"} = getTypeType($TypeInfoId, $TypeId);
1143 if($TypeAttr{"Type"} eq "Struct" and has_methods($TypeId))
1144 {
1145 $TypeAttr{"Type"} = "Class";
1146 }
1147 if(($TypeAttr{"Type"} eq "Struct") or ($TypeAttr{"Type"} eq "Class"))
1148 {
1149 setBaseClasses($TypeInfoId, $TypeId, \%TypeAttr);
1150 }
1151 setTypeMemb($TypeInfoId, $TypeId, \%TypeAttr);
1152 $TypeAttr{"Tid"} = $TypeId;
1153 $TypeAttr{"TDid"} = $TypeInfoId;
1154 $Tid_TDid{$Version}{$TypeId} = $TypeInfoId;
1155 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}})
1156 {
1157 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
1158 }
1159 return %TypeAttr;
1160 }
1161
1162 sub has_methods($)
1163 {
1164 my $TypeId = $_[0];
1165 my $Info = $LibInfo{$Version}{$TypeId}{"info"};
1166 return ($Info=~/(fncs)[ ]*:[ ]*@([0-9]+) /);
1167 }
1168
1169 sub setBaseClasses($$$)
1170 {
1171 my ($TypeInfoId, $TypeId, $TypeAttr) = @_;
1172 my $Info = $LibInfo{$Version}{$TypeId}{"info"};
1173 if($Info =~ /binf[ ]*:[ ]*@([0-9]+) /)
1174 {
1175 $Info = $LibInfo{$Version}{$1}{"info"};
1176 while($Info =~ /accs[ ]*:[ ]*([a-z]+) /)
1177 {
1178 last if($Info !~ s/accs[ ]*:[ ]*([a-z]+) //);
1179 my $Access = $1;
1180 last if($Info !~ s/binf[ ]*:[ ]*@([0-9]+) //);
1181 my $BInfoId = $1;
1182 my $ClassId = getBinfClassId($BInfoId);
1183 if($Access eq "pub")
1184 {
1185 $TypeAttr->{"BaseClass"}{$ClassId} = "public";
1186 }
1187 elsif($Access eq "prot")
1188 {
1189 $TypeAttr->{"BaseClass"}{$ClassId} = "protected";
1190 }
1191 elsif($Access eq "priv")
1192 {
1193 $TypeAttr->{"BaseClass"}{$ClassId} = "private";
1194 }
1195 else
1196 {
1197 $TypeAttr->{"BaseClass"}{$ClassId} = "private";
1198 }
1199 }
1200 }
1201 }
1202
1203 sub getBinfClassId($)
1204 {
1205 my $Info = $LibInfo{$Version}{$_[0]}{"info"};
1206 $Info =~ /type[ ]*:[ ]*@([0-9]+) /;
1207 return $1;
1208 }
1209
1210 sub get_func_signature($)
1211 {
1212 my $FuncInfoId = $_[0];
1213 my $PureSignature = $FuncDescr{$Version}{$FuncInfoId}{"ShortName"};
1214 my @ParamTypes = ();
1215 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$FuncDescr{$Version}{$FuncInfoId}{"Param"}}))
1216 {#checking parameters
1217 my $ParamType_Id = $FuncDescr{$Version}{$FuncInfoId}{"Param"}{$ParamPos}{"type"};
1218 my $ParamType_Name = uncover_typedefs($TypeDescr{$Version}{getTypeDeclId($ParamType_Id)}{$ParamType_Id}{"Name"});
1219 @ParamTypes = (@ParamTypes, $ParamType_Name);
1220 }
1221 $PureSignature = $PureSignature."(".join(", ", @ParamTypes).")";
1222 $PureSignature = delete_keywords($PureSignature);
1223 return correctName($PureSignature);
1224 }
1225
1226 sub delete_keywords($)
1227 {
1228 my $TypeName = $_[0];
1229 $TypeName =~ s/(\W|\A)(enum |struct |union |class )/$1/g;
1230 return $TypeName;
1231 }
1232
1233 sub uncover_typedefs($)
1234 {
1235 my $TypeName = $_[0];
1236 return "" if(not $TypeName);
1237 return $Cache{"uncover_typedefs"}{$Version}{$TypeName} if(defined $Cache{"uncover_typedefs"}{$Version}{$TypeName});
1238 my ($TypeName_New, $TypeName_Pre) = (correctName($TypeName), "");
1239 while($TypeName_New ne $TypeName_Pre)
1240 {
1241 $TypeName_Pre = $TypeName_New;
1242 my $TypeName_Copy = $TypeName_New;
1243 my %Words = ();
1244 while($TypeName_Copy=~s/(\W|\A)([a-z_][\w:]*)(\W|\Z)//io)
1245 {
1246 my $Word = $2;
1247 next if(not $Word or $Word=~/\A(true|false|const|int|long|void|short|float|unsigned|char|double|class|struct|union|enum)\Z/);
1248 $Words{$Word} = 1;
1249 }
1250 foreach my $Word (keys(%Words))
1251 {
1252 my $BaseType_Name = $Typedef_BaseName{$Version}{$Word};
1253 next if($TypeName_New=~/(\W|\A)(struct $Word|union $Word|enum $Word)(\W|\Z)/);
1254 next if(not $BaseType_Name);
1255 if($BaseType_Name=~/\([*]+\)/)
1256 {
1257 $TypeName_New =~ /$Word(.*)\Z/;
1258 my $Type_Suffix = $1;
1259 $TypeName_New = $BaseType_Name;
1260 if($TypeName_New =~ s/\(([*]+)\)/($1 $Type_Suffix)/)
1261 {
1262 $TypeName_New = correctName($TypeName_New);
1263 }
1264 }
1265 else
1266 {
1267 if($TypeName_New =~ s/(\W|\A)$Word(\W|\Z)/$1$BaseType_Name$2/g)
1268 {
1269 $TypeName_New = correctName($TypeName_New);
1270 }
1271 }
1272 }
1273 }
1274 $Cache{"uncover_typedefs"}{$Version}{$TypeName} = $TypeName_New;
1275 return $TypeName_New;
1276 }
1277
1278 sub isInternal($)
1279 {
1280 my $FuncInfoId = $_[0];
1281 my $FuncInfo = $LibInfo{$Version}{$_[0]}{"info"};
1282 return 0 if($FuncInfo !~ /mngl[ ]*:[ ]*@([0-9]+) /);
1283 my $FuncMnglNameInfoId = $1;
1284 return ($LibInfo{$Version}{$FuncMnglNameInfoId}{"info"} =~ /\*[ ]*INTERNAL[ ]*\*/);
1285 }
1286
1287 sub set_Class_And_Namespace($)
1288 {
1289 my $FuncInfoId = $_[0];
1290 my $FuncInfo = $LibInfo{$Version}{$FuncInfoId}{"info"};
1291 if($FuncInfo =~ /scpe[ ]*:[ ]*@([0-9]+) /)
1292 {
1293 my $NameSpaceInfoId = $1;
1294 if($LibInfo{$Version}{$NameSpaceInfoId}{"info_type"} eq "namespace_decl")
1295 {
1296 my $NameSpaceInfo = $LibInfo{$Version}{$NameSpaceInfoId}{"info"};
1297 if($NameSpaceInfo =~ /name[ ]*:[ ]*@([0-9]+) /)
1298 {
1299 my $NameSpaceId = $1;
1300 my $NameSpaceIdentifier = $LibInfo{$Version}{$NameSpaceId}{"info"};
1301 if($NameSpaceIdentifier =~ /strg[ ]*:[ ]*(.*)[ ]+lngt/)
1302 {
1303 my $NameSpace = $1;
1304 $NameSpace =~ s/[ ]+\Z//g;
1305 $FuncDescr{$Version}{$FuncInfoId}{"NameSpace"} = $NameSpace;
1306 }
1307 }
1308 }
1309 elsif($LibInfo{$Version}{$NameSpaceInfoId}{"info_type"} eq "record_type")
1310 {
1311 $FuncDescr{$Version}{$FuncInfoId}{"Class"} = $NameSpaceInfoId;
1312 }
1313 }
1314 }
1315
1316 sub getFuncDescr($)
1317 {
1318 my $FuncInfoId = $_[0];
1319 return if(isInternal($FuncInfoId));
1320 ($FuncDescr{$Version}{$FuncInfoId}{"Header"}, $FuncDescr{$Version}{$FuncInfoId}{"Line"}) = getLocation($FuncInfoId);
1321 if(not $FuncDescr{$Version}{$FuncInfoId}{"Header"} or $FuncDescr{$Version}{$FuncInfoId}{"Header"}=~/\<built\-in\>|\<internal\>/)
1322 {
1323 delete($FuncDescr{$Version}{$FuncInfoId});
1324 return;
1325 }
1326 setFuncAccess($FuncInfoId);
1327 setFuncKind($FuncInfoId);
1328 if($FuncDescr{$Version}{$FuncInfoId}{"PseudoTemplate"})
1329 {
1330 delete($FuncDescr{$Version}{$FuncInfoId});
1331 return;
1332 }
1333 $FuncDescr{$Version}{$FuncInfoId}{"Type"} = getFuncType($FuncInfoId);
1334 $FuncDescr{$Version}{$FuncInfoId}{"Return"} = getFuncReturn($FuncInfoId);
1335 delete($FuncDescr{$Version}{$FuncInfoId}{"Return"}) if(not $FuncDescr{$Version}{$FuncInfoId}{"Return"});
1336 $FuncDescr{$Version}{$FuncInfoId}{"ShortName"} = getFuncShortName(getFuncOrig($FuncInfoId));
1337 if($FuncDescr{$Version}{$FuncInfoId}{"ShortName"} =~ /\._/)
1338 {
1339 delete($FuncDescr{$Version}{$FuncInfoId});
1340 return;
1341 }
1342 if(defined $TemplateInstance_Func{$Version}{$FuncInfoId})
1343 {
1344 my @TmplParams = ();
1345 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$TemplateInstance_Func{$Version}{$FuncInfoId}}))
1346 {
1347 my $Param = get_TemplateParam($TemplateInstance_Func{$Version}{$FuncInfoId}{$ParamPos});
1348 if($Param eq "")
1349 {
1350 delete($FuncDescr{$Version}{$FuncInfoId});
1351 return;
1352 }
1353 push(@TmplParams, $Param);
1354 }
1355 $FuncDescr{$Version}{$FuncInfoId}{"ShortName"} .= "<".join(", ", @TmplParams).">";
1356 }
1357 setFuncParams($FuncInfoId);
1358 $FuncDescr{$Version}{$FuncInfoId}{"MnglName"} = getFuncMnglName($FuncInfoId);
1359 if($FuncDescr{$Version}{$FuncInfoId}{"MnglName"} and $FuncDescr{$Version}{$FuncInfoId}{"MnglName"}!~/\A_Z/)
1360 {
1361 delete($FuncDescr{$Version}{$FuncInfoId});
1362 return;
1363 }
1364
1365 if((is_in_library($FuncDescr{$Version}{$FuncInfoId}{"ShortName"}, $Version) or $CheckHeadersOnly) and not $FuncDescr{$Version}{$FuncInfoId}{"MnglName"} and ($FuncDescr{$Version}{$FuncInfoId}{"Type"} eq "Function"))
1366 {
1367 $FuncDescr{$Version}{$FuncInfoId}{"MnglName"} = $FuncDescr{$Version}{$FuncInfoId}{"ShortName"};
1368 }
1369 set_Class_And_Namespace($FuncInfoId);
1370 if(not $FuncDescr{$Version}{$FuncInfoId}{"MnglName"} and not $FuncDescr{$Version}{$FuncInfoId}{"Class"})
1371 {#this section only for c++ functions without class that have not been mangled in the tree
1372 $FuncDescr{$Version}{$FuncInfoId}{"MnglName"} = $mangled_name{get_func_signature($FuncInfoId)};
1373 }
1374 if(not is_in_library($FuncDescr{$Version}{$FuncInfoId}{"MnglName"}, $Version) and not $CheckHeadersOnly)
1375 {#src only
1376 delete($FuncDescr{$Version}{$FuncInfoId});
1377 return;
1378 }
1379 if($FuncDescr{$Version}{$FuncInfoId}{"Constructor"} or $FuncDescr{$Version}{$FuncInfoId}{"Destructor"})
1380 {
1381 delete($FuncDescr{$Version}{$FuncInfoId}{"Return"});
1382 }
1383 my $FuncBody = getFuncBody($FuncInfoId);
1384 if($FuncBody eq "defined")
1385 {
1386 $FuncDescr{$Version}{$FuncInfoId}{"InLine"} = 1;
1387 }
1388 if($CheckHeadersOnly and $FuncDescr{$Version}{$FuncInfoId}{"InLine"})
1389 {
1390 delete($FuncDescr{$Version}{$FuncInfoId});
1391 return;
1392 }
1393 if(($FuncDescr{$Version}{$FuncInfoId}{"Type"} eq "Method") or $FuncDescr{$Version}{$FuncInfoId}{"Constructor"} or $FuncDescr{$Version}{$FuncInfoId}{"Destructor"})
1394 {
1395 if($FuncDescr{$Version}{$FuncInfoId}{"MnglName"}!~/\A_Z/)
1396 {
1397 delete($FuncDescr{$Version}{$FuncInfoId});
1398 return;
1399 }
1400 }
1401 if(getFuncSpec($FuncInfoId) eq "Virt")
1402 {#virtual methods
1403 $FuncDescr{$Version}{$FuncInfoId}{"Virt"} = 1;
1404 }
1405 if(getFuncSpec($FuncInfoId) eq "PureVirt")
1406 {#pure virtual methods
1407 $FuncDescr{$Version}{$FuncInfoId}{"PureVirt"} = 1;
1408 }
1409 if($FuncDescr{$Version}{$FuncInfoId}{"MnglName"} =~ /\A_Z/ and $FuncDescr{$Version}{$FuncInfoId}{"Class"})
1410 {
1411 if($FuncDescr{$Version}{$FuncInfoId}{"Type"} eq "Function")
1412 {#static methods
1413 $FuncDescr{$Version}{$FuncInfoId}{"Static"} = 1;
1414 }
1415 }
1416 if(getFuncLink($FuncInfoId) eq "Static")
1417 {
1418 $FuncDescr{$Version}{$FuncInfoId}{"Static"} = 1;
1419 }
1420 delete($FuncDescr{$Version}{$FuncInfoId}{"Type"});
1421 }
1422
1423 sub getFuncBody($)
1424 {
1425 my $FuncInfo = $LibInfo{$Version}{$_[0]}{"info"};
1426 if($FuncInfo =~ /body[ ]*:[ ]*undefined(\ |\Z)/i)
1427 {
1428 return "undefined";
1429 }
1430 elsif($FuncInfo =~ /body[ ]*:[ ]*@([0-9]+)(\ |\Z)/i)
1431 {
1432 return "defined";
1433 }
1434 else
1435 {
1436 return "";
1437 }
1438 }
1439
1440 sub getTypeShortName($)
1441 {
1442 my $TypeName = $_[0];
1443 $TypeName =~ s/\<.*\>//g;
1444 $TypeName =~ s/.*\:\://g;
1445 return $TypeName;
1446 }
1447
1448 sub getBackRef($)
1449 {
1450 my $TypeInfo = $LibInfo{$Version}{$_[0]}{"info"};
1451 if($TypeInfo =~ /name[ ]*:[ ]*@([0-9]+) /)
1452 {
1453 return $1;
1454 }
1455 else
1456 {
1457 return "";
1458 }
1459 }
1460
1461 sub getTypeId($)
1462 {
1463 my $TypeInfo = $LibInfo{$Version}{$_[0]}{"info"};
1464 if($TypeInfo =~ /type[ ]*:[ ]*@([0-9]+) /)
1465 {
1466 return $1;
1467 }
1468 else
1469 {
1470 return "";
1471 }
1472 }
1473
1474 sub getFuncId($)
1475 {
1476 my $FuncInfo = $LibInfo{$Version}{$_[0]}{"info"};
1477 if($FuncInfo =~ /type[ ]*:[ ]*@([0-9]+) /)
1478 {
1479 return $1;
1480 }
1481 else
1482 {
1483 return "";
1484 }
1485 }
1486
1487 sub setTypeMemb($$)
1488 {
1489 my ($TypeDeclId, $TypeId, $TypeAttr) = @_;
1490 my $TypeInfo = $LibInfo{$Version}{$TypeId}{"info"};
1491 my $TypeMembInfoId;
1492 my $TypeType = $TypeAttr->{"Type"};
1493 my $Position = 0;
1494 my $BasePosition = 0;
1495 my $TypeTypeInfoId;
1496 my $StructMembName;
1497 if($TypeType eq "Enum")
1498 {
1499 $TypeMembInfoId = getEnumMembInfoId($TypeId);
1500 while($TypeMembInfoId)
1501 {
1502 $TypeAttr->{"Memb"}{$Position}{"value"} = getEnumMembVal($TypeMembInfoId);
1503 my $MembName = getEnumMembName($TypeMembInfoId);
1504 $TypeAttr->{"Memb"}{$Position}{"name"} = getEnumMembName($TypeMembInfoId);
1505 $EnumMembName_Id{$Version}{getTreeAttr($TypeMembInfoId, "valu")} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
1506 $TypeMembInfoId = getNextMembInfoId($TypeMembInfoId);
1507 $Position += 1;
1508 }
1509 }
1510 elsif(($TypeType eq "Struct") or ($TypeType eq "Class") or ($TypeType eq "Union"))
1511 {
1512 $TypeMembInfoId = getStructMembInfoId($TypeId);
1513 while($TypeMembInfoId)
1514 {
1515 if($LibInfo{$Version}{$TypeMembInfoId}{"info_type"} ne "field_decl")
1516 {
1517 $TypeMembInfoId = getNextStructMembInfoId($TypeMembInfoId);
1518 next;
1519 }
1520 $StructMembName = getStructMembName($TypeMembInfoId);
1521 if($StructMembName =~ /_vptr\./)
1522 {#virtual tables
1523 $TypeMembInfoId = getNextStructMembInfoId($TypeMembInfoId);
1524 next;
1525 }
1526 if(not $StructMembName)
1527 {#base classes
1528 #$TypeAttr->{"Base"}{$BasePosition}{"type"} = getStructMembType($TypeMembInfoId);
1529 #$TypeAttr->{"Base"}{$BasePosition}{"access"} = getStructMembAccess($TypeMembInfoId);
1530 $BasePosition += 1;
1531 $TypeMembInfoId = getNextStructMembInfoId($TypeMembInfoId);
1532 next;
1533 }
1534 $TypeAttr->{"Memb"}{$Position}{"type"} = getStructMembType($TypeMembInfoId);
1535 $TypeAttr->{"Memb"}{$Position}{"name"} = $StructMembName;
1536 $TypeAttr->{"Memb"}{$Position}{"access"} = getStructMembAccess($TypeMembInfoId);
1537 $TypeAttr->{"Memb"}{$Position}{"bitfield"} = getStructMembBitFieldSize($TypeMembInfoId);
1538
1539 $TypeMembInfoId = getNextStructMembInfoId($TypeMembInfoId);
1540 $Position += 1;
1541 }
1542 }
1543 }
1544
1545 sub setFuncParams($)
1546 {
1547 my $FuncInfoId = $_[0];
1548 my $ParamInfoId = getFuncParamInfoId($FuncInfoId);
1549 my $FunctionType = getFuncType($FuncInfoId);
1550 if($FunctionType eq "Method")
1551 {
1552 $ParamInfoId = getNextElem($ParamInfoId);
1553 }
1554 my $Position = 0;
1555 while($ParamInfoId)
1556 {
1557 my $ParamTypeId = getFuncParamType($ParamInfoId);
1558 last if($TypeDescr{$Version}{getTypeDeclId($ParamTypeId)}{$ParamTypeId}{"Name"} eq "void");
1559 if($TypeDescr{$Version}{getTypeDeclId($ParamTypeId)}{$ParamTypeId}{"Type"} eq "Restrict")
1560 {#delete restrict spec
1561 $ParamTypeId = getRestrictBase($ParamTypeId);
1562 }
1563 $FuncDescr{$Version}{$FuncInfoId}{"Param"}{$Position}{"type"} = $ParamTypeId;
1564 $FuncDescr{$Version}{$FuncInfoId}{"Param"}{$Position}{"name"} = getFuncParamName($ParamInfoId);
1565 if(not $FuncDescr{$Version}{$FuncInfoId}{"Param"}{$Position}{"name"})
1566 {
1567 $FuncDescr{$Version}{$FuncInfoId}{"Param"}{$Position}{"name"} = "p".($Position+1);
1568 }
1569 $ParamInfoId = getNextElem($ParamInfoId);
1570 $Position += 1;
1571 }
1572 if(detect_nolimit_args($FuncInfoId))
1573 {
1574 $FuncDescr{$Version}{$FuncInfoId}{"Param"}{$Position}{"type"} = -1;
1575 }
1576 }
1577
1578 sub detect_nolimit_args($)
1579 {
1580 my $FuncInfoId = $_[0];
1581 my $FuncTypeId = getFuncTypeId($FuncInfoId);
1582 my $ParamListElemId = getFuncParamTreeListId($FuncTypeId);
1583 my $HaveVoid = 0;
1584 my $Position = 0;
1585 while($ParamListElemId)
1586 {
1587 my $ParamTypeId = getTreeAttr($ParamListElemId, "valu");
1588 if($TypeDescr{$Version}{getTypeDeclId($ParamTypeId)}{$ParamTypeId}{"Name"} eq "void")
1589 {
1590 $HaveVoid = 1;
1591 last;
1592 }
1593 $ParamListElemId = getNextElem($ParamListElemId);
1594 $Position += 1;
1595 }
1596 return ($Position>=1 and not $HaveVoid);
1597 }
1598
1599 sub getFuncParamTreeListId($)
1600 {
1601 my $FuncTypeId = $_[0];
1602 if($LibInfo{$Version}{$FuncTypeId}{"info"} =~ /prms[ ]*:[ ]*@([0-9]+) /)
1603 {
1604 return $1;
1605 }
1606 else
1607 {
1608 return "";
1609 }
1610 }
1611
1612 sub getTreeAttr($$)
1613 {
1614 my ($Id, $Attr) = @_;
1615 if($LibInfo{$Version}{$Id}{"info"} =~ /$Attr[ ]*:[ ]*@([0-9]+) /)
1616 {
1617 return $1;
1618 }
1619 else
1620 {
1621 return "";
1622 }
1623 }
1624
1625 sub getRestrictBase($)
1626 {
1627 my $TypeId = $_[0];
1628 my $TypeDeclId = getTypeDeclId($TypeId);
1629 my $BaseTypeId = $TypeDescr{$Version}{$TypeDeclId}{$TypeId}{"BaseType"}{"Tid"};
1630 my $BaseTypeDeclId = $TypeDescr{$Version}{$TypeDeclId}{$TypeId}{"BaseType"}{"TDid"};
1631 return $BaseTypeId;
1632 }
1633
1634 sub setFuncAccess($)
1635 {
1636 my $FuncInfoId = $_[0];
1637 if($LibInfo{$Version}{$FuncInfoId}{"info"} =~ /accs[ ]*:[ ]*([a-zA-Z]+) /)
1638 {
1639 my $Access = $1;
1640 if($Access eq "prot")
1641 {
1642 $FuncDescr{$Version}{$FuncInfoId}{"Protected"} = 1;
1643 }
1644 elsif($Access eq "priv")
1645 {
1646 $FuncDescr{$Version}{$FuncInfoId}{"Private"} = 1;
1647 }
1648 }
1649 }
1650
1651 sub setTypeAccess($$)
1652 {
1653 my ($TypeId, $TypeAttr) = @_;
1654 my $TypeInfo = $LibInfo{$Version}{$TypeId}{"info"};
1655 if($TypeInfo =~ /accs[ ]*:[ ]*([a-zA-Z]+) /)
1656 {
1657 my $Access = $1;
1658 if($Access eq "prot")
1659 {
1660 $TypeAttr->{"Protected"} = 1;
1661 }
1662 elsif($Access eq "priv")
1663 {
1664 $TypeAttr->{"Private"} = 1;
1665 }
1666 }
1667 }
1668
1669 sub setFuncKind($)
1670 {
1671 my $FuncInfoId = $_[0];
1672 if($LibInfo{$Version}{$FuncInfoId}{"info"} =~ /pseudo tmpl/)
1673 {
1674 $FuncDescr{$Version}{$FuncInfoId}{"PseudoTemplate"} = 1;
1675 }
1676 elsif($LibInfo{$Version}{$FuncInfoId}{"info"} =~ /note[ ]*:[ ]*constructor /)
1677 {
1678 $FuncDescr{$Version}{$FuncInfoId}{"Constructor"} = 1;
1679 }
1680 elsif($LibInfo{$Version}{$FuncInfoId}{"info"} =~ /note[ ]*:[ ]*destructor /)
1681 {
1682 $FuncDescr{$Version}{$FuncInfoId}{"Destructor"} = 1;
1683 }
1684 }
1685
1686 sub getFuncSpec($)
1687 {
1688 my $FuncInfoId = $_[0];
1689 my $FuncInfo = $LibInfo{$Version}{$FuncInfoId}{"info"};
1690 if($FuncInfo =~ m/spec[ ]*:[ ]*pure /)
1691 {
1692 return "PureVirt";
1693 }
1694 elsif($FuncInfo =~ m/spec[ ]*:[ ]*virt /)
1695 {
1696 return "Virt";
1697 }
1698 else
1699 {
1700 if($FuncInfo =~ /spec[ ]*:[ ]*([a-zA-Z]+) /)
1701 {
1702 return $1;
1703 }
1704 else
1705 {
1706 return "";
1707 }
1708 }
1709 }
1710
1711 sub getFuncClass($)
1712 {
1713 my $FuncInfoId = $_[0];
1714 my $FuncInfo = $LibInfo{$Version}{$FuncInfoId}{"info"};
1715 if($FuncInfo =~ /scpe[ ]*:[ ]*@([0-9]+) /)
1716 {
1717 return $1;
1718 }
1719 else
1720 {
1721 return "";
1722 }
1723 }
1724
1725 sub getFuncLink($)
1726 {
1727 my $FuncInfoId = $_[0];
1728 my $FuncInfo = $LibInfo{$Version}{$FuncInfoId}{"info"};
1729 if($FuncInfo =~ /link[ ]*:[ ]*static /)
1730 {
1731 return "Static";
1732 }
1733 else
1734 {
1735 if($FuncInfo =~ /link[ ]*:[ ]*([a-zA-Z]+) /)
1736 {
1737 return $1;
1738 }
1739 else
1740 {
1741 return "";
1742 }
1743 }
1744 }
1745
1746 sub getNextElem($)
1747 {
1748 my $FuncInfoId = $_[0];
1749 my $FuncInfo = $LibInfo{$Version}{$FuncInfoId}{"info"};
1750 if($FuncInfo =~ /chan[ ]*:[ ]*@([0-9]+) /)
1751 {
1752 return $1;
1753 }
1754 else
1755 {
1756 return "";
1757 }
1758 }
1759
1760 sub getFuncParamInfoId($)
1761 {
1762 my $FuncInfoId = $_[0];
1763 my $FuncInfo = $LibInfo{$Version}{$FuncInfoId}{"info"};
1764 if($FuncInfo =~ /args[ ]*:[ ]*@([0-9]+) /)
1765 {
1766 return $1;
1767 }
1768 else
1769 {
1770 return "";
1771 }
1772 }
1773
1774 sub getFuncParamType($)
1775 {
1776 my $ParamInfoId = $_[0];
1777 my $ParamInfo = $LibInfo{$Version}{$ParamInfoId}{"info"};
1778 if($ParamInfo =~ /type[ ]*:[ ]*@([0-9]+) /)
1779 {
1780 return $1;
1781 }
1782 else
1783 {
1784 return "";
1785 }
1786 }
1787
1788 sub getFuncParamName($)
1789 {
1790 my $ParamInfoId = $_[0];
1791 my $ParamInfo = $LibInfo{$Version}{$ParamInfoId}{"info"};
1792 return "" if($ParamInfo !~ /name[ ]*:[ ]*@([0-9]+) /);
1793 my $NameInfoId = $1;
1794 return "" if($LibInfo{$Version}{$NameInfoId}{"info"} !~ /strg[ ]*:[ ]*(.*)[ ]+lngt/);
1795 my $FuncParamName = $1;
1796 $FuncParamName =~ s/[ ]+\Z//g;
1797 return $FuncParamName;
1798 }
1799
1800 sub getEnumMembInfoId($)
1801 {
1802 my $TypeInfoId = $_[0];
1803 my $TypeInfo = $LibInfo{$Version}{$TypeInfoId}{"info"};
1804 if($TypeInfo =~ /csts[ ]*:[ ]*@([0-9]+) /)
1805 {
1806 return $1;
1807 }
1808 else
1809 {
1810 return "";
1811 }
1812 }
1813
1814 sub getStructMembInfoId($)
1815 {
1816 my $TypeInfoId = $_[0];
1817 my $TypeInfo = $LibInfo{$Version}{$TypeInfoId}{"info"};
1818 if($TypeInfo =~ /flds[ ]*:[ ]*@([0-9]+) /)
1819 {
1820 return $1;
1821 }
1822 else
1823 {
1824 return "";
1825 }
1826 }
1827
1828 sub getNameSpace($)
1829 {
1830 my $TypeInfoId = $_[0];
1831 my $TypeInfo = $LibInfo{$Version}{$TypeInfoId}{"info"};
1832 return "" if($TypeInfo !~ /scpe[ ]*:[ ]*@([0-9]+) /);
1833 my $NameSpaceInfoId = $1;
1834 if($LibInfo{$Version}{$NameSpaceInfoId}{"info_type"} eq "namespace_decl")
1835 {
1836 my $NameSpaceInfo = $LibInfo{$Version}{$NameSpaceInfoId}{"info"};
1837 if($NameSpaceInfo =~ /name[ ]*:[ ]*@([0-9]+) /)
1838 {
1839 my $NameSpaceId = $1;
1840 my $NameSpaceIdentifier = $LibInfo{$Version}{$NameSpaceId}{"info"};
1841 return "" if($NameSpaceIdentifier !~ /strg[ ]*:[ ]*(.*)[ ]+lngt/);
1842 my $NameSpace = $1;
1843 $NameSpace =~ s/[ ]+\Z//g;
1844 my $BaseNameSpace = getNameSpace($NameSpaceInfoId);
1845 $NameSpace = $BaseNameSpace."::".$NameSpace if($BaseNameSpace);
1846 return $NameSpace;
1847 }
1848 else
1849 {
1850 return "";
1851 }
1852 }
1853 elsif($LibInfo{$Version}{$NameSpaceInfoId}{"info_type"} eq "record_type")
1854 {
1855 my %NameSpaceAttr = getTypeAttr(getTypeDeclId($NameSpaceInfoId), $NameSpaceInfoId);
1856 return $NameSpaceAttr{"Name"};
1857 }
1858 else
1859 {
1860 return "";
1861 }
1862 }
1863
1864 sub getNameSpaceId($)
1865 {
1866 my $TypeInfoId = $_[0];
1867 my $TypeInfo = $LibInfo{$Version}{$TypeInfoId}{"info"};
1868 if($TypeInfo =~ /scpe[ ]*:[ ]*@([0-9]+) /)
1869 {
1870 return $1;
1871 }
1872 else
1873 {
1874 return "";
1875 }
1876 }
1877
1878 sub getEnumMembName($)
1879 {
1880 my $TypeMembInfoId = $_[0];
1881 return "" if($LibInfo{$Version}{$TypeMembInfoId}{"info"} !~ /purp[ ]*:[ ]*@([0-9]+)/);
1882 my $Purp = $1;
1883 return "" if($LibInfo{$Version}{$Purp}{"info"} !~ /strg[ ]*:[ ]*(.*)[ ]+lngt/);
1884 my $EnumMembName = $1;
1885 $EnumMembName =~ s/[ ]+\Z//g;
1886 return $EnumMembName;
1887 }
1888
1889 sub getStructMembName($)
1890 {
1891 my $TypeMembInfoId = $_[0];
1892 return "" if($LibInfo{$Version}{$TypeMembInfoId}{"info"} !~ /name[ ]*:[ ]*@([0-9]+) /);
1893 my $NameInfoId = $1;
1894 return "" if($LibInfo{$Version}{$NameInfoId}{"info"} !~ /strg[ ]*:[ ]*(.*)[ ]+lngt/);
1895 my $StructMembName = $1;
1896 $StructMembName =~ s/[ ]+\Z//g;
1897 return $StructMembName;
1898 }
1899
1900 sub getEnumMembVal($)
1901 {
1902 my $TypeMembInfoId = $_[0];
1903 return "" if($LibInfo{$Version}{$TypeMembInfoId}{"info"} !~ /valu[ ]*:[ ]*@([0-9]+) /);
1904 my $Valu = $1;
1905 if($LibInfo{$Version}{$Valu}{"info"} =~ /low[ ]*:[ ]*(-?[0-9]+) /)
1906 {
1907 return $1;
1908 }
1909 else
1910 {
1911 return "";
1912 }
1913 }
1914
1915 sub getSize($)
1916 {
1917 my $Info = $LibInfo{$Version}{$_[0]}{"info"};
1918 if($Info =~ /size[ ]*:[ ]*@([0-9]+) /)
1919 {
1920 my $SizeInfoId = $1;
1921 if($LibInfo{$Version}{$SizeInfoId}{"info"} =~ /low[ ]*:[ ]*(-?[0-9]+) /)
1922 {
1923 return $1;
1924 }
1925 else
1926 {
1927 return "";
1928 }
1929 }
1930 else
1931 {
1932 return 0;
1933 }
1934 }
1935
1936 sub getStructMembType($)
1937 {
1938 my $TypeMembInfoId = $_[0];
1939 if($LibInfo{$Version}{$TypeMembInfoId}{"info"} =~ /type[ ]*:[ ]*@([0-9]+) /)
1940 {
1941 return $1;
1942 }
1943 else
1944 {
1945 return "";
1946 }
1947 }
1948
1949 sub getStructMembBitFieldSize($)
1950 {
1951 my $TypeMembInfoId = $_[0];
1952 if($LibInfo{$Version}{$TypeMembInfoId}{"info"} =~ / bitfield /)
1953 {
1954 return getSize($TypeMembInfoId);
1955 }
1956 else
1957 {
1958 return 0;
1959 }
1960 }
1961
1962 sub getStructMembAccess($)
1963 {
1964 my $MembInfo = $LibInfo{$Version}{$_[0]}{"info"};
1965 if($MembInfo =~ /accs[ ]*:[ ]*([a-zA-Z]+) /)
1966 {
1967 my $Access = $1;
1968 if($Access eq "prot")
1969 {
1970 return "protected";
1971 }
1972 elsif($Access eq "priv")
1973 {
1974 return "private";
1975 }
1976 else
1977 {
1978 return "public";
1979 }
1980 }
1981 else
1982 {
1983 return "public";
1984 }
1985 }
1986
1987 sub getNextMembInfoId($)
1988 {
1989 my $TypeMembInfoId = $_[0];
1990 if($LibInfo{$Version}{$TypeMembInfoId}{"info"} =~ /chan[ ]*:[ ]*@([0-9]+) /)
1991 {
1992 return $1;
1993 }
1994 else
1995 {
1996 return "";
1997 }
1998 }
1999
2000 sub getNextStructMembInfoId($)
2001 {
2002 my $TypeMembInfoId = $_[0];
2003 if($LibInfo{$Version}{$TypeMembInfoId}{"info"} =~ /chan[ ]*:[ ]*@([0-9]+) /)
2004 {
2005 return $1;
2006 }
2007 else
2008 {
2009 return "";
2010 }
2011 }
2012
2013 sub fieldHasName($)
2014 {
2015 my $TypeMembInfoId = $_[0];
2016 if($LibInfo{$Version}{$TypeMembInfoId}{"info_type"} eq "field_decl")
2017 {
2018 if($LibInfo{$Version}{$TypeMembInfoId}{"info"} =~ /name[ ]*:[ ]*@([0-9]+) /)
2019 {
2020 return $1;
2021 }
2022 else
2023 {
2024 return "";
2025 }
2026 }
2027 else
2028 {
2029 return 0;
2030 }
2031 }
2032
2033 sub getTypeHeader($)
2034 {
2035 my $TypeInfo = $LibInfo{$Version}{$_[0]}{"info"};
2036 if($TypeInfo =~ /srcp[ ]*:[ ]*([0-9a-zA-Z\_\-\<\>\.\+]+):([0-9]+) /)
2037 {
2038 return ($1, $2);
2039 }
2040 else
2041 {
2042 return ();
2043 }
2044 }
2045
2046 sub register_header($$$)
2047 {
2048 my ($Destination, $Position, $LibVersion) = @_;
2049 return if(not $Destination);
2050 if($Destination=~/\A\// and not -f $Destination)
2051 {
2052 print "\nERROR: specified header \'$Destination\' does not exist\n";
2053 return;
2054 }
2055 my $Header_Name = get_FileName($Destination);
2056 $Headers{$LibVersion}{$Destination}{"Name"} = $Header_Name;
2057 $Headers{$LibVersion}{$Destination}{"Position"} = $Position;
2058 $Headers{$LibVersion}{$Destination}{"Identity"} = $Destination;
2059 $HeaderName_Destinations{$LibVersion}{$Header_Name}{$Destination} = 1;
2060 }
2061
2062 sub headerSearch($)
2063 {
2064 my $LibVersion = $_[0];
2065 foreach my $Dest (split("\n", $Descriptor{$LibVersion}{"Include_Paths"}))
2066 {
2067 $Dest =~ s/\A\s+|\s+\Z//g;
2068 next if(not $Dest);
2069 if(not -e $Dest)
2070 {
2071 print "ERROR: can't access \'$Dest\'\n";
2072 }
2073 $Header_Dependency{$LibVersion}{$Dest} = 1;
2074 }
2075 foreach my $Dest (split("\n", $Descriptor{$LibVersion}{"Headers"}))
2076 {#fill %Header_Dependency
2077 if(-d $Dest)
2078 {
2079 foreach my $Dir (cmd_find($Dest,"d",""))
2080 {
2081 chomp($Dir);
2082 $Header_Dependency{$LibVersion}{$Dir} = 1;
2083 }
2084 }
2085 elsif(-f $Dest)
2086 {
2087 $Header_Dependency{$LibVersion}{get_Dir($Dest)} = 1;
2088 }
2089 }
2090 my $Position = 0;
2091 foreach my $Dest (split("\n", $Descriptor{$LibVersion}{"Headers"}))
2092 {
2093 $Dest =~ s/\A\s+|\s+\Z//g;
2094 next if(not $Dest);
2095 if(is_header($Dest, $LibVersion))
2096 {
2097 register_header($Dest, $Position, $LibVersion);
2098 $Position += 1;
2099 }
2100 elsif(-d $Dest)
2101 {
2102 foreach my $Destination (sort {lc($a) cmp lc($b)} (cmd_find($Dest,"f","")))
2103 {
2104 chomp($Destination);
2105 next if(not is_header($Destination, $LibVersion));
2106 register_header($Destination, $Position, $LibVersion);
2107 $Position += 1;
2108 }
2109 }
2110 else
2111 {
2112 print "WARNING: \'$Dest\' was not found in the specified include paths\n";
2113 register_header($Dest, $Position, $LibVersion);
2114 $Position += 1;
2115 }
2116 }
2117 if(keys(%{$Headers{$LibVersion}})==1)
2118 {
2119 my $Destination = (keys(%{$Headers{$LibVersion}}))[0];
2120 $Headers{$LibVersion}{$Destination}{"Identity"} = $Headers{$LibVersion}{$Destination}{"Name"};
2121 }
2122 foreach my $Header_Name (keys(%{$HeaderName_Destinations{$LibVersion}}))
2123 {#set relative paths (for dublicates)
2124 if(keys(%{$HeaderName_Destinations{$LibVersion}{$Header_Name}})>1)
2125 {
2126 my $FirstDest = (keys(%{$HeaderName_Destinations{$LibVersion}{$Header_Name}}))[0];
2127 my $Prefix = get_Dir($FirstDest);
2128 while($Prefix =~ /\A(.+)\/[^\/]+\Z/)
2129 {
2130 my $NewPrefix = $1;
2131 my $Changes_Number = 0;
2132 my %Identity = ();
2133 foreach my $Dest (keys(%{$HeaderName_Destinations{$LibVersion}{$Header_Name}}))
2134 {
2135 if($Dest =~ /\A$Prefix\/(.*)\Z/)
2136 {
2137 $Identity{$Dest} = $1;
2138 $Changes_Number+=1;
2139 }
2140 }
2141 if($Changes_Number eq keys(%{$HeaderName_Destinations{$LibVersion}{$Header_Name}}))
2142 {
2143 foreach my $Dest (keys(%{$HeaderName_Destinations{$LibVersion}{$Header_Name}}))
2144 {
2145 $Headers{$LibVersion}{$Dest}{"Identity"} = $Identity{$Dest};
2146 }
2147 last;
2148 }
2149 $Prefix = $NewPrefix;
2150 }
2151 }
2152 }
2153 if(not keys(%{$Headers{$LibVersion}}))
2154 {
2155 print "ERROR: header files were not found\n";
2156 exit(1);
2157 }
2158 }
2159
2160 sub get_FileName($)
2161 {
2162 my $Path = $_[0];
2163 if($Path =~ /\A(.*\/)([^\/]*)\Z/)
2164 {
2165 return $2;
2166 }
2167 else
2168 {
2169 return $Path;
2170 }
2171 }
2172
2173 sub get_Dir($)
2174 {
2175 my $Path = $_[0];
2176 return "" if($Path =~ m*\A\./*);
2177 if($Path =~ /\A(.*)\/([^\/]*)\Z/)
2178 {
2179 return $1;
2180 }
2181 else
2182 {
2183 return "";
2184 }
2185 }
2186
2187 sub esc($)
2188 {
2189 my $Str = $_[0];
2190 $Str =~ s/([()\[\]{}$ &'"`;,<>])/\\$1/g;
2191 return $Str;
2192 }
2193
2194 sub getLocation($)
2195 {
2196 my $TypeInfo = $LibInfo{$Version}{$_[0]}{"info"};
2197 if($TypeInfo =~ /srcp[ ]*:[ ]*([0-9a-zA-Z\_\-\<\>\.\+]+):([0-9]+) /)
2198 {
2199 return ($1, $2);
2200 }
2201 else
2202 {
2203 return ();
2204 }
2205 }
2206
2207 sub getHeader($)
2208 {
2209 my $TypeInfo = $LibInfo{$Version}{$_[0]}{"info"};
2210 if($TypeInfo =~ /srcp[ ]*:[ ]*([0-9a-zA-Z\_\-\<\>\.\+]+):([0-9]+) /)
2211 {
2212 return $1;
2213 }
2214 else
2215 {
2216 return "";
2217 }
2218 }
2219
2220 sub getLine($)
2221 {
2222 my $TypeInfo = $LibInfo{$Version}{$_[0]}{"info"};
2223 if($TypeInfo =~ /srcp[ ]*:[ ]*([0-9a-zA-Z\_\-\<\>\.\+]+):([0-9]+) /)
2224 {
2225 return $2;
2226 }
2227 else
2228 {
2229 return "";
2230 }
2231 }
2232
2233 sub getTypeType($$)
2234 {
2235 my ($TypeDeclId, $TypeId) = @_;
2236 return "Const" if($LibInfo{$Version}{$TypeId}{"info"} =~ /qual[ ]*:[ ]*c / and $LibInfo{$Version}{$TypeId}{"info"} =~ /unql[ ]*:[ ]*\@/);
2237 return "Typedef" if($LibInfo{$Version}{$TypeId}{"info"} =~ /unql[ ]*:/ and $LibInfo{$Version}{$TypeId}{"info"} !~ /qual[ ]*:/);
2238 return "Volatile" if($LibInfo{$Version}{$TypeId}{"info"} =~ /qual[ ]*:[ ]*v / and $LibInfo{$Version}{$TypeId}{"info"} =~ /unql[ ]*:[ ]*\@/);
2239 return "Restrict" if($LibInfo{$Version}{$TypeId}{"info"} =~ /qual[ ]*:[ ]*r / and $LibInfo{$Version}{$TypeId}{"info"} =~ /unql[ ]*:[ ]*\@/);
2240 my $TypeType = getTypeTypeByTypeId($TypeId);
2241 if($TypeType eq "Struct")
2242 {
2243 if($TypeDeclId and $LibInfo{$Version}{$TypeDeclId}{"info_type"} eq "template_decl")
2244 {
2245 return "Template";
2246 }
2247 else
2248 {
2249 return "Struct";
2250 }
2251 }
2252 else
2253 {
2254 return $TypeType;
2255 }
2256
2257 }
2258
2259 sub getTypeTypeByTypeId($)
2260 {
2261 my $TypeId = $_[0];
2262 my $TypeType = $LibInfo{$Version}{$TypeId}{"info_type"};
2263 if($TypeType =~ /integer_type|real_type|boolean_type|void_type|complex_type/)
2264 {
2265 return "Intrinsic";
2266 }
2267 elsif(isFuncPtr($TypeId))
2268 {
2269 return "FuncPtr";
2270 }
2271 elsif($TypeType eq "pointer_type")
2272 {
2273 return "Pointer";
2274 }
2275 elsif($TypeType eq "reference_type")
2276 {
2277 return "Ref";
2278 }
2279 elsif($TypeType eq "union_type")
2280 {
2281 return "Union";
2282 }
2283 elsif($TypeType eq "enumeral_type")
2284 {
2285 return "Enum";
2286 }
2287 elsif($TypeType eq "record_type")
2288 {
2289 return "Struct";
2290 }
2291 elsif($TypeType eq "array_type")
2292 {
2293 return "Array";
2294 }
2295 elsif($TypeType eq "complex_type")
2296 {
2297 return "Intrinsic";
2298 }
2299 elsif($TypeType eq "function_type")
2300 {
2301 return "FunctionType";
2302 }
2303 elsif($TypeType eq "method_type")
2304 {
2305 return "MethodType";
2306 }
2307 else
2308 {
2309 return "Unknown";
2310 }
2311 }
2312
2313 sub getNameByInfo($)
2314 {
2315 my $TypeInfo = $LibInfo{$Version}{$_[0]}{"info"};
2316 return "" if($TypeInfo !~ /name[ ]*:[ ]*@([0-9]+) /);
2317 my $TypeNameInfoId = $1;
2318 return "" if($LibInfo{$Version}{$TypeNameInfoId}{"info"} !~ /strg[ ]*:[ ]*(.*)[ ]+lngt/);
2319 my $TypeName = $1;
2320 $TypeName =~ s/[ ]+\Z//g;
2321 return $TypeName;
2322 }
2323
2324 sub getFuncShortName($)
2325 {
2326 my $FuncInfo = $LibInfo{$Version}{$_[0]}{"info"};
2327 if($FuncInfo =~ / operator /)
2328 {
2329 if($FuncInfo =~ /note[ ]*:[ ]*conversion /)
2330 {
2331 return "operator ".get_TypeName($FuncDescr{$Version}{$_[0]}{"Return"});
2332 }
2333 else
2334 {
2335 return "" if($FuncInfo !~ / operator[ ]+([a-zA-Z]+) /);
2336 return "operator".$Operator_Indication{$1};
2337 }
2338 }
2339 else
2340 {
2341 return "" if($FuncInfo !~ /name[ ]*:[ ]*@([0-9]+) /);
2342 my $FuncNameInfoId = $1;
2343 return "" if($LibInfo{$Version}{$FuncNameInfoId}{"info"} !~ /strg[ ]*:[ ]*([^ ]*)[ ]+lngt/);
2344 return $1;
2345 }
2346 }
2347
2348 sub getFuncMnglName($)
2349 {
2350 my $FuncInfo = $LibInfo{$Version}{$_[0]}{"info"};
2351 return "" if($FuncInfo !~ /mngl[ ]*:[ ]*@([0-9]+) /);
2352 my $FuncMnglNameInfoId = $1;
2353 return "" if($LibInfo{$Version}{$FuncMnglNameInfoId}{"info"} !~ /strg[ ]*:[ ]*([^ ]*)[ ]+/);
2354 my $FuncMnglName = $1;
2355 $FuncMnglName =~ s/[ ]+\Z//g;
2356 return $FuncMnglName;
2357 }
2358
2359 sub getFuncReturn($)
2360 {
2361 my $FuncInfo = $LibInfo{$Version}{$_[0]}{"info"};
2362 return "" if($FuncInfo !~ /type[ ]*:[ ]*@([0-9]+) /);
2363 my $FuncTypeInfoId = $1;
2364 return "" if($LibInfo{$Version}{$FuncTypeInfoId}{"info"} !~ /retn[ ]*:[ ]*@([0-9]+) /);
2365 my $FuncReturnTypeId = $1;
2366 if($TypeDescr{$Version}{getTypeDeclId($FuncReturnTypeId)}{$FuncReturnTypeId}{"Type"} eq "Restrict")
2367 {#delete restrict spec
2368 $FuncReturnTypeId = getRestrictBase($FuncReturnTypeId);
2369 }
2370 return $FuncReturnTypeId;
2371 }
2372
2373 sub getFuncOrig($)
2374 {
2375 my $FuncInfo = $LibInfo{$Version}{$_[0]}{"info"};
2376 if($FuncInfo =~ /orig[ ]*:[ ]*@([0-9]+) /)
2377 {
2378 return $1;
2379 }
2380 else
2381 {
2382 return $_[0];
2383 }
2384 }
2385
2386 sub unmangleArray(@)
2387 {
2388 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
2389 {
2390 my @Half = splice(@_, 0, ($#_+1)/2);
2391 return (unmangleArray(@Half), unmangleArray(@_))
2392 }
2393 else
2394 {
2395 my $UnmangleCommand = "c++filt ".join(" ", @_);
2396 return split("\n", `$UnmangleCommand`);
2397 }
2398 }
2399
2400 sub get_Signature($$)
2401 {
2402 my ($Interface, $LibVersion) = @_;
2403 return $Cache{"get_Signature"}{$Interface}{$LibVersion} if($Cache{"get_Signature"}{$Interface}{$LibVersion});
2404 my ($MnglName, $SymbolVersion) = ($Interface, "");
2405 if($Interface =~ /\A([^@]+)[\@]+([^@]+)\Z/)
2406 {
2407 ($MnglName, $SymbolVersion) = ($1, $2);
2408 }
2409 if($MnglName =~ /\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZThn|_ZTv0_n)/)
2410 {
2411 $Cache{"get_Signature"}{$Interface}{$LibVersion} = $tr_name{$MnglName}.(($SymbolVersion)?"\@".$SymbolVersion:"");
2412 return $Cache{"get_Signature"}{$Interface}{$LibVersion};
2413 }
2414 if(not $CompleteSignature{$LibVersion}{$Interface})
2415 {
2416 if($Interface =~ /\A_Z/)
2417 {
2418 $Cache{"get_Signature"}{$Interface}{$LibVersion} = $tr_name{$MnglName}.(($SymbolVersion)?"\@".$SymbolVersion:"");
2419 return $Cache{"get_Signature"}{$Interface}{$LibVersion};
2420 }
2421 else
2422 {
2423 $Cache{"get_Signature"}{$Interface}{$LibVersion} = $Interface;
2424 return $Interface;
2425 }
2426 }
2427 my ($Func_Signature, @Param_Types_FromUnmangledName) = ();
2428 my $ShortName = $CompleteSignature{$LibVersion}{$Interface}{"ShortName"};
2429 if($Interface =~ /\A_Z/)
2430 {
2431 if($CompleteSignature{$LibVersion}{$Interface}{"Class"})
2432 {
2433 $Func_Signature = get_TypeName($CompleteSignature{$LibVersion}{$Interface}{"Class"}, $LibVersion)."::".(($CompleteSignature{$LibVersion}{$Interface}{"Destructor"})?"~":"").$ShortName;
2434 }
2435 else
2436 {
2437 $Func_Signature = $ShortName;
2438 }
2439 @Param_Types_FromUnmangledName = get_Signature_Parts($tr_name{$MnglName}, 0);
2440 }
2441 else
2442 {
2443 $Func_Signature = $MnglName;
2444 }
2445 my @ParamArray = ();
2446 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Interface}{"Param"}}))
2447 {
2448 next if($Pos eq "");
2449 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Interface}{"Param"}{$Pos}{"type"};
2450 my $ParamTypeName = $TypeDescr{$LibVersion}{$Tid_TDid{$LibVersion}{$ParamTypeId}}{$ParamTypeId}{"Name"};
2451 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos] if(not $ParamTypeName);
2452 if(my $ParamName = $CompleteSignature{$LibVersion}{$Interface}{"Param"}{$Pos}{"name"})
2453 {
2454 if($ParamTypeName=~/\([*]+\)/)
2455 {
2456 $ParamTypeName=~s/\(([*]+)\)/\($1$ParamName\)/;
2457 push(@ParamArray, $ParamTypeName);
2458 }
2459 else
2460 {
2461 push(@ParamArray, $ParamTypeName." ".$ParamName);
2462 }
2463 }
2464 else
2465 {
2466 push(@ParamArray, $ParamTypeName);
2467 }
2468 }
2469 if(not $CompleteSignature{$LibVersion}{$Interface}{"Data"})
2470 {
2471 if($Interface=~/\A_Z/)
2472 {
2473 if($CompleteSignature{$LibVersion}{$Interface}{"Constructor"})
2474 {
2475 if($Interface=~/C1/)
2476 {
2477 $Func_Signature .= " [in-charge]";
2478 }
2479 elsif($Interface=~/C2/)
2480 {
2481 $Func_Signature .= " [not-in-charge]";
2482 }
2483 }
2484 elsif($CompleteSignature{$LibVersion}{$Interface}{"Destructor"})
2485 {
2486 if($Interface=~/D1/)
2487 {
2488 $Func_Signature .= " [in-charge]";
2489 }
2490 elsif($Interface=~/D2/)
2491 {
2492 $Func_Signature .= " [not-in-charge]";
2493 }
2494 elsif($Interface=~/D0/)
2495 {
2496 $Func_Signature .= " [in-charge-deleting]";
2497 }
2498 }
2499 }
2500 $Func_Signature .= " (".join(", ", @ParamArray).")";
2501 }
2502 if($Interface=~/\A_ZNK/)
2503 {
2504 $Func_Signature .= " const";
2505 }
2506 $Func_Signature .= "\@".$SymbolVersion if($SymbolVersion);
2507 $Cache{"get_Signature"}{$Interface}{$LibVersion} = $Func_Signature;
2508 return $Func_Signature;
2509 }
2510
2511 sub getVarNameByAttr($)
2512 {
2513 my $FuncInfoId = $_[0];
2514 my $VarName;
2515 return "" if(not $FuncDescr{$Version}{$FuncInfoId}{"ShortName"});
2516 if($FuncDescr{$Version}{$FuncInfoId}{"Class"})
2517 {
2518 $VarName .= $TypeDescr{$Version}{getTypeDeclId($FuncDescr{$Version}{$FuncInfoId}{"Class"})}{$FuncDescr{$Version}{$FuncInfoId}{"Class"}}{"Name"};
2519 $VarName .= "::";
2520 }
2521 $VarName .= $FuncDescr{$Version}{$FuncInfoId}{"ShortName"};
2522 return $VarName;
2523 }
2524
2525 sub mangleFuncName($)
2526 {
2527 my $FuncId = $_[0];
2528 }
2529
2530 sub getFuncType($)
2531 {
2532 my $FuncInfo = $LibInfo{$Version}{$_[0]}{"info"};
2533 return "" if($FuncInfo !~ /type[ ]*:[ ]*@([0-9]+) /);
2534 my $FuncTypeInfoId = $1;
2535 my $FunctionType = $LibInfo{$Version}{$FuncTypeInfoId}{"info_type"};
2536 if($FunctionType eq "method_type")
2537 {
2538 return "Method";
2539 }
2540 elsif($FunctionType eq "function_type")
2541 {
2542 return "Function";
2543 }
2544 else
2545 {
2546 return $FunctionType;
2547 }
2548 }
2549
2550 sub getFuncTypeId($)
2551 {
2552 my $FuncInfo = $LibInfo{$Version}{$_[0]}{"info"};
2553 if($FuncInfo =~ /type[ ]*:[ ]*@([0-9]+)( |\Z)/)
2554 {
2555 return $1;
2556 }
2557 else
2558 {
2559 return 0;
2560 }
2561 }
2562
2563 sub isNotAnon($)
2564 {
2565 return (not isAnon($_[0]));
2566 }
2567
2568 sub isAnon($)
2569 {
2570 return (($_[0] =~ m/\.\_[0-9]+/) or ($_[0] =~ m/anon-/));
2571 }
2572
2573 sub unmangled_Compact($$)
2574 #Removes all non-essential (for C++ language) whitespace from a string. If
2575 #the whitespace is essential it will be replaced with exactly one ' '
2576 #character. Works correctly only for unmangled names.
2577 #If level > 1 is supplied, can relax its intent to compact the string.
2578 {
2579 my $result=$_[0];
2580 my $level = $_[1] || 1;
2581 my $o1 = ($level>1)?' ':'';
2582 #First, we reduce all spaces that we can
2583 my $coms='[-()<>:*&~!|+=%@~"?.,/[^'."']";
2584 my $coms_nobr='[-()<:*&~!|+=%@~"?.,'."']";
2585 my $clos='[),;:\]]';
2586 $result=~s/^\s+//gm;
2587 $result=~s/\s+$//gm;
2588 $result=~s/((?!\n)\s)+/ /g;
2589 $result=~s/(\w+)\s+($coms+)/$1$o1$2/gm;
2590 #$result=~s/(\w)(\()/$1$o1$2/gm if $o1;
2591 $result=~s/($coms+)\s+(\w+)/$1$o1$2/gm;
2592 $result=~s/(\()\s+(\w)/$1$2/gm if $o1;
2593 $result=~s/(\w)\s+($clos)/$1$2/gm;
2594 $result=~s/($coms+)\s+($coms+)/$1 $2/gm;
2595 $result=~s/($coms_nobr+)\s+($coms+)/$1$o1$2/gm;
2596 $result=~s/($coms+)\s+($coms_nobr+)/$1$o1$2/gm;
2597 #don't forget about >> and <:. In unmangled names global-scope modifier
2598 #is not used, so <: will always be a digraph and requires no special treatment.
2599 #We also try to remove other parts that are better to be removed here than in other places
2600 #double-cv
2601 $result=~s/\bconst\s+const\b/const/gm;
2602 $result=~s/\bvolatile\s+volatile\b/volatile/gm;
2603 $result=~s/\bconst\s+volatile\b\s+const\b/const volatile/gm;
2604 $result=~s/\bvolatile\s+const\b\s+volatile\b/const volatile/gm;
2605 #Place cv in proper order
2606 $result=~s/\bvolatile\s+const\b/const volatile/gm;
2607 return $result;
2608 }
2609
2610 sub unmangled_PostProcess($)
2611 {
2612 my $result = $_[0];
2613 #s/\bunsigned int\b/unsigned/g;
2614 $result =~ s/\bshort unsigned int\b/unsigned short/g;
2615 $result =~ s/\bshort int\b/short/g;
2616 $result =~ s/\blong long unsigned int\b/unsigned long long/g;
2617 $result =~ s/\blong unsigned int\b/unsigned long/g;
2618 $result =~ s/\blong long int\b/long long/g;
2619 $result =~ s/\blong int\b/long/g;
2620 $result =~ s/\)const\b/\) const/g;
2621 $result =~ s/\blong long unsigned\b/unsigned long long/g;
2622 $result =~ s/\blong unsigned\b/unsigned long/g;
2623 return $result;
2624 }
2625
2626 # From libtodb2/libtodb.pm
2627 # Trim string spaces.
2628 sub trim($)
2629 {
2630 my $string = shift;
2631 $string =~ s/^\s+//;
2632 $string =~ s/\s+$//;
2633 return $string;
2634 }
2635
2636 sub correctName($)
2637 {#type name correction
2638 my $CorrectName = $_[0];
2639 $CorrectName = unmangled_Compact($CorrectName, 1);
2640 $CorrectName = unmangled_PostProcess($CorrectName);
2641 return $CorrectName;
2642 }
2643
2644 sub getDump_AllInOne()
2645 {
2646 return if(not keys(%Headers));
2647 `mkdir -p temp && rm -f temp/*`;
2648 my $Header_Depend = "";
2649 foreach my $Dep (sort {length($a) <=> length($b)} keys(%{$Header_Dependency{$Version}}))
2650 {
2651 $Header_Depend .= " -I".esc($Dep);
2652 }
2653 my $Lib_VersionName = esc($TargetLibraryName)."_v".$Version;
2654 open(LIB_HEADER, ">temp/$TargetLibraryName"."_v$Version.h");
2655 foreach my $Preamble_Header (sort {int($Include_Preamble{$Version}{$a}{"Position"})<=>int($Include_Preamble{$Version}{$b}{"Position"})} keys(%{$Include_Preamble{$Version}}))
2656 {
2657 print LIB_HEADER "#include <$Preamble_Header>\n";
2658 }
2659 foreach my $Destination (sort {int($Headers{$Version}{$a}{"Position"})<=>int($Headers{$Version}{$b}{"Position"})} keys(%{$Headers{$Version}}))
2660 {
2661 my $HName = get_FileName($Destination);
2662 next if($Include_Preamble{$Version}{$Destination} or ($Include_Preamble{$Version}{$HName} and $HeaderName_Destinations{$Version}{$HName} and keys(%{$HeaderName_Destinations{$Version}{$HName}})==1));
2663 print LIB_HEADER "#include <$Destination>\n";
2664 }
2665 close(LIB_HEADER);
2666 system("g++ >".esc($ERR_PATH{$Version})." 2>&1 -fdump-translation-unit temp/$Lib_VersionName.h $CompilerOptions{$Version} $Header_Depend");
2667 if($?)
2668 {
2669 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";
2670 }
2671 $ConstantsSrc{$Version} = cmd_preprocessor("temp/$Lib_VersionName.h", $CompilerOptions{$Version}." ".$Header_Depend, "define\\ \\|undef\\ \\|#[ ]\\+[0-9]\\+ \".*\"");
2672 system("mkdir", "-p", "header_compile_errors/$TargetLibraryName/temp/");
2673 system("cp", "-f", "temp/$TargetLibraryName"."_v$Version.h", "header_compile_errors/$TargetLibraryName/temp/");
2674 return (split("\n", `find . -maxdepth 1 -name "$Lib_VersionName\.h*\.tu"`))[0];
2675 }
2676
2677 sub getDump_Separately($)
2678 {
2679 `mkdir -p temp`;
2680 `rm -f temp/*`;
2681 my $Destination = $_[0];
2682 my $Header_Depend = "";
2683 foreach my $Dep (sort {length($a) <=> length($b)} keys(%{$Header_Dependency{$Version}}))
2684 {
2685 $Header_Depend .= " -I".esc($Dep);
2686 }
2687 my $Lib_VersionName = esc($TargetLibraryName)."_v".$Version;
2688 open(LIB_HEADER, ">temp/$TargetLibraryName"."_v$Version.h");
2689 foreach my $Preamble_Header (sort {int($Include_Preamble{$Version}{$a}{"Position"})<=>int($Include_Preamble{$Version}{$b}{"Position"})} keys(%{$Include_Preamble{$Version}}))
2690 {
2691 print LIB_HEADER "#include <$Preamble_Header>\n";
2692 }
2693 my $Destination_HName = get_FileName($Destination);
2694 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) ))
2695 {
2696 print LIB_HEADER "#include <$Destination>\n";
2697 }
2698 close(LIB_HEADER);
2699 system("g++ >>".esc($ERR_PATH{$Version})." 2>&1 -fdump-translation-unit temp/$Lib_VersionName.h $CompilerOptions{$Version} $Header_Depend");
2700 if($?)
2701 {
2702 $HeaderCompileError{get_FileName($Destination)} = 1;
2703 }
2704 $ConstantsSrc{$Version} .= cmd_preprocessor("temp/$Lib_VersionName.h", $CompilerOptions{$Version}." ".$Header_Depend, "define\\ \\|undef\\ \\|#[ ]\\+[0-9]\\+ \".*\"");
2705 return (split("\n", `find . -maxdepth 1 -name "$Lib_VersionName\.h*\.tu"`))[0];
2706 }
2707
2708 sub cmd_file($)
2709 {
2710 my $Path = $_[0];
2711 return "" if(not $Path or not -e $Path);
2712 my $Cmd = "file ".esc($Path);
2713 my $Cmd_Out = `$Cmd`;
2714 return $Cmd_Out;
2715 }
2716
2717 sub cmd_preprocessor($$$)
2718 {
2719 my ($Path, $AddOpt, $Grep) = @_;
2720 return "" if(not $Path or not -f $Path);
2721 my $Cmd = "g++ -dD -E -x c++-header ".esc($Path)." 2>/dev/null $AddOpt";
2722 if($Grep)
2723 {
2724 $Cmd .= " | grep \"$Grep\"";
2725 }
2726 my $Cmd_Out = `$Cmd`;
2727 return $Cmd_Out;
2728 }
2729
2730 sub cmd_cat($$)
2731 {
2732 my ($Path, $Grep) = @_;
2733 return "" if(not $Path or not -e $Path);
2734 my $Cmd = "cat ".esc($Path);
2735 if($Grep)
2736 {
2737 $Cmd .= " | grep \"$Grep\"";
2738 }
2739 my $Cmd_Out = `$Cmd`;
2740 return $Cmd_Out;
2741 }
2742
2743 sub cmd_find($$$)
2744 {
2745 my ($Path, $Type, $Name) = @_;
2746 return () if(not $Path or not -e $Path);
2747 my $Cmd = "find ".esc($Path);
2748 if($Type)
2749 {
2750 $Cmd .= " -type $Type";
2751 }
2752 if($Name)
2753 {
2754 $Cmd .= " -name \"$Name\"";
2755 }
2756 return split("\n", `$Cmd`);
2757 }
2758
2759 sub cmd_tar($)
2760 {
2761 my $Path = $_[0];
2762 return "" if(not $Path or not -e $Path);
2763 my $Cmd = "tar -xvzf ".esc($Path);
2764 my $Cmd_Out = `$Cmd`;
2765 return $Cmd_Out;
2766 }
2767
2768 sub is_header($$)
2769 {
2770 my ($Destination, $LibVersion) = @_;
2771 return 0 if(-d $Destination);
2772 return 1 if($Destination =~ /\.(h|hh|hhh|hpp|tcc)\Z/i);
2773 return 0 if($Destination =~ /\.\w+\Z/i);#cpp|c|gch|tu|fs|pas
2774 if($Destination =~ /\A\//)
2775 {
2776 return (cmd_file($Destination) =~ /:[ ]*ASCII C[\+]* program text/);
2777 }
2778 else
2779 {
2780 foreach my $Prefix (keys(%{$Header_Dependency{$LibVersion}}))
2781 {
2782 my $Path = $Prefix."/".$Destination;
2783 if(-f $Path)
2784 {
2785 if(cmd_file($Path) =~ /:[ ]*ASCII C[\+]* program text/)
2786 {
2787 return 1;
2788 }
2789 }
2790 }
2791 return 0;
2792 }
2793 }
2794
2795 sub parseHeaders_AllInOne($)
2796 {
2797 $Version = $_[0];
2798 print "checking header(s) ".$Descriptor{$Version}{"Version"}." ...\n";
2799 system("mkdir", "-p", "header_compile_errors/".$TargetLibraryName);
2800 system("rm", "-fr", $ERR_PATH{$Version});
2801 my $DumpPath = getDump_AllInOne();
2802 if(not $DumpPath)
2803 {
2804 print "\nERROR: can't create gcc syntax tree for header(s)\nyou can see compilation errors in the file '$ERR_PATH{$Version}'\n";
2805 exit(1);
2806 }
2807 getInfo($DumpPath);
2808 parse_constants();
2809 system("rm", "-fr", "temp");
2810 }
2811
2812 sub parseHeader($)
2813 {
2814 my $Destination = $_[0];
2815 my $DumpPath = getDump_Separately($Destination);
2816 if(not $DumpPath)
2817 {
2818 print "ERROR: can't create gcc syntax tree for header\nyou can see compilation errors in the file '$ERR_PATH{$Version}'\n";
2819 exit(1);
2820 }
2821 getInfo($DumpPath);
2822 parse_constants();
2823 system("rm", "-fr", "temp");
2824 }
2825
2826 sub is_in_library($$)
2827 {
2828 my ($MnglName, $LibVersion) = @_;
2829 return ($Interface_Library{$LibVersion}{$MnglName} or ($SymVer{$LibVersion}{$MnglName} and $Interface_Library{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}));
2830 }
2831
2832 sub prepareInterfaces($)
2833 {
2834 my $LibVersion = $_[0];
2835 my (@MnglNames, @UnMnglNames) = ();
2836 if($CheckHeadersOnly)
2837 {
2838 foreach my $FuncInfoId (sort keys(%{$FuncDescr{$LibVersion}}))
2839 {
2840 if($FuncDescr{$LibVersion}{$FuncInfoId}{"MnglName"} =~ /\A_Z/)
2841 {
2842 push(@MnglNames, $FuncDescr{$LibVersion}{$FuncInfoId}{"MnglName"});
2843 }
2844 }
2845 if($#MnglNames > -1)
2846 {
2847 @UnMnglNames = reverse(unmangleArray(@MnglNames));
2848 foreach my $FuncInfoId (sort keys(%{$FuncDescr{$LibVersion}}))
2849 {
2850 if($FuncDescr{$LibVersion}{$FuncInfoId}{"MnglName"} =~ /\A_Z/)
2851 {
2852 my $UnmangledName = pop(@UnMnglNames);
2853 $tr_name{$FuncDescr{$LibVersion}{$FuncInfoId}{"MnglName"}} = $UnmangledName;
2854 }
2855 }
2856 }
2857 }
2858 my (%NotMangled_Int, %Mangled_Int) = ();
2859 foreach my $FuncInfoId (keys(%{$FuncDescr{$LibVersion}}))
2860 {
2861 my $MnglName = $FuncDescr{$LibVersion}{$FuncInfoId}{"MnglName"};
2862 if($MnglName=~/\A_Z/)
2863 {
2864 $Mangled_Int{$FuncInfoId} = $MnglName;
2865 }
2866 else
2867 {
2868 $NotMangled_Int{$FuncInfoId} = $MnglName;
2869 }
2870 next if(not $MnglName or not is_in_library($MnglName, $LibVersion) and not $CheckHeadersOnly);
2871 next if($MnglName =~ /\A_Z/ and $tr_name{$MnglName} =~ /\.\_[0-9]/);
2872 next if(not $FuncDescr{$LibVersion}{$FuncInfoId}{"Header"});
2873 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$FuncDescr{$LibVersion}{$FuncInfoId}};
2874 #interface and its symlink have same signatures
2875 if($SymVer{$LibVersion}{$MnglName})
2876 {
2877 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$FuncDescr{$LibVersion}{$FuncInfoId}};
2878 }
2879 delete($FuncDescr{$LibVersion}{$FuncInfoId});
2880 }
2881 if(keys(%Mangled_Int))
2882 {
2883 foreach my $Interface_Id (keys(%NotMangled_Int))
2884 {
2885 delete($CompleteSignature{$LibVersion}{$NotMangled_Int{$Interface_Id}});
2886 }
2887 }
2888 }
2889
2890 my %UsedType;
2891 sub cleanData($)
2892 {
2893 my $LibVersion = $_[0];
2894 foreach my $FuncInfoId (keys(%{$FuncDescr{$LibVersion}}))
2895 {
2896 my $MnglName = $FuncDescr{$LibVersion}{$FuncInfoId}{"MnglName"};
2897 if(not $MnglName or not is_in_library($MnglName, $LibVersion) and not $CheckHeadersOnly)
2898 {
2899 delete($FuncDescr{$LibVersion}{$FuncInfoId});
2900 next;
2901 }
2902 if(defined $InterfacesListPath and not $InterfacesList{$MnglName})
2903 {
2904 delete($FuncDescr{$LibVersion}{$FuncInfoId});
2905 next;
2906 }
2907 if(defined $AppPath and not $InterfacesList_App{$MnglName})
2908 {
2909 delete($FuncDescr{$LibVersion}{$FuncInfoId});
2910 next;
2911 }
2912 my %FuncInfo = %{$FuncDescr{$LibVersion}{$FuncInfoId}};
2913 detect_TypeUsing($Tid_TDid{$LibVersion}{$FuncInfo{"Return"}}, $FuncInfo{"Return"}, $LibVersion);
2914 detect_TypeUsing($Tid_TDid{$LibVersion}{$FuncInfo{"Class"}}, $FuncInfo{"Class"}, $LibVersion);
2915 foreach my $Param_Pos (keys(%{$FuncInfo{"Param"}}))
2916 {
2917 my $Param_TypeId = $FuncInfo{"Param"}{$Param_Pos}{"type"};
2918 detect_TypeUsing($Tid_TDid{$LibVersion}{$Param_TypeId}, $Param_TypeId, $LibVersion);
2919 }
2920 }
2921 foreach my $TDid (keys(%{$TypeDescr{$LibVersion}}))
2922 {
2923 foreach my $Tid (keys(%{$TypeDescr{$LibVersion}{$TDid}}))
2924 {
2925 if(not $UsedType{$LibVersion}{$TDid}{$Tid})
2926 {
2927 delete($TypeDescr{$LibVersion}{$TDid}{$Tid});
2928 if(not keys(%{$TypeDescr{$LibVersion}{$TDid}}))
2929 {
2930 delete($TypeDescr{$LibVersion}{$TDid});
2931 }
2932 delete($Tid_TDid{$LibVersion}{$Tid}) if($Tid_TDid{$LibVersion}{$Tid} eq $TDid);
2933 }
2934 }
2935 }
2936 }
2937
2938 sub detect_TypeUsing($$$)
2939 {
2940 my ($TypeDeclId, $TypeId, $LibVersion) = @_;
2941 return if($UsedType{$LibVersion}{$TypeDeclId}{$TypeId});
2942 my %Type = get_Type($TypeDeclId, $TypeId, $LibVersion);
2943 if($Type{"Type"} =~ /Struct|Union|Class|FuncPtr|Enum/)
2944 {
2945 $UsedType{$LibVersion}{$TypeDeclId}{$TypeId} = 1;
2946 foreach my $Memb_Pos (keys(%{$Type{"Memb"}}))
2947 {
2948 my $Member_TypeId = $Type{"Memb"}{$Memb_Pos}{"type"};
2949 detect_TypeUsing($Tid_TDid{$LibVersion}{$Member_TypeId}, $Member_TypeId, $LibVersion);
2950 }
2951 if($Type{"Type"} eq "FuncPtr")
2952 {
2953 my $ReturnType = $Type{"Return"};
2954 detect_TypeUsing($Tid_TDid{$LibVersion}{$ReturnType}, $ReturnType, $LibVersion);
2955 }
2956 }
2957 elsif($Type{"Type"} =~ /Const|Pointer|Ref|Volatile|Restrict|Array|/)
2958 {
2959 $UsedType{$LibVersion}{$TypeDeclId}{$TypeId} = 1;
2960 detect_TypeUsing($Type{"BaseType"}{"TDid"}, $Type{"BaseType"}{"Tid"}, $LibVersion);
2961 }
2962 elsif($Type{"Type"} eq "Intrinsic")
2963 {
2964 $UsedType{$LibVersion}{$TypeDeclId}{$TypeId} = 1;
2965 }
2966 else
2967 {
2968 delete($TypeDescr{$LibVersion}{$TypeDeclId}{$TypeId});
2969 if(not keys(%{$TypeDescr{$LibVersion}{$TypeDeclId}}))
2970 {
2971 delete($TypeDescr{$LibVersion}{$TypeDeclId});
2972 }
2973 delete($Tid_TDid{$LibVersion}{$TypeId}) if($Tid_TDid{$LibVersion}{$TypeId} eq $TypeDeclId);
2974 }
2975 }
2976
2977 sub initializeClassVirtFunc($)
2978 {
2979 my $LibVersion = $_[0];
2980 foreach my $Interface (keys(%{$CompleteSignature{$LibVersion}}))
2981 {
2982 if($CompleteSignature{$LibVersion}{$Interface}{"Virt"})
2983 {
2984 my $ClassName = $TypeDescr{$LibVersion}{$Tid_TDid{$LibVersion}{$CompleteSignature{$LibVersion}{$Interface}{"Class"}}}{$CompleteSignature{$LibVersion}{$Interface}{"Class"}}{"Name"};
2985 $ClassVirtFunc{$LibVersion}{$ClassName}{$Interface} = 1;
2986 $ClassIdVirtFunc{$LibVersion}{$CompleteSignature{$LibVersion}{$Interface}{"Class"}}{$Interface} = 1;
2987 $ClassId{$LibVersion}{$ClassName} = $CompleteSignature{$LibVersion}{$Interface}{"Class"};
2988 }
2989 }
2990 }
2991
2992 sub checkVirtFuncRedefinitions($)
2993 {
2994 my $LibVersion = $_[0];
2995 foreach my $Class_Name (keys(%{$ClassVirtFunc{$LibVersion}}))
2996 {
2997 $CheckedTypes{$Class_Name} = 1;
2998 foreach my $VirtFuncName (keys(%{$ClassVirtFunc{$LibVersion}{$Class_Name}}))
2999 {
3000 $CompleteSignature{$LibVersion}{$VirtFuncName}{"VirtualRedefine"} = find_virtual_method_in_base_classes($VirtFuncName, $ClassId{$LibVersion}{$Class_Name}, $LibVersion);
3001 }
3002 }
3003 }
3004
3005 sub setVirtFuncPositions($)
3006 {
3007 my $LibVersion = $_[0];
3008 foreach my $Class_Name (keys(%{$ClassVirtFunc{$LibVersion}}))
3009 {
3010 $CheckedTypes{$Class_Name} = 1;
3011 my $Position = 0;
3012 foreach my $VirtFuncName (sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} keys(%{$ClassVirtFunc{$LibVersion}{$Class_Name}}))
3013 {
3014 if($ClassVirtFunc{1}{$Class_Name}{$VirtFuncName} and $ClassVirtFunc{2}{$Class_Name}{$VirtFuncName} and not $CompleteSignature{1}{$VirtFuncName}{"VirtualRedefine"} and not $CompleteSignature{2}{$VirtFuncName}{"VirtualRedefine"})
3015 {
3016 $CompleteSignature{$LibVersion}{$VirtFuncName}{"Position"} = $Position;
3017 $Position += 1;
3018 }
3019 }
3020 }
3021 }
3022
3023 sub check_VirtualTable($$)
3024 {
3025 my ($TargetFunction, $LibVersion) = @_;
3026 my $Class_Id = $CompleteSignature{$LibVersion}{$TargetFunction}{"Class"};
3027 my $Class_DId = $Tid_TDid{$LibVersion}{$Class_Id};
3028 my %Class_Type = get_Type($Class_DId, $Class_Id, $LibVersion);
3029 $CheckedTypes{$Class_Type{"Name"}} = 1;
3030 foreach my $VirtFuncName (keys(%{$ClassVirtFunc{2}{$Class_Type{"Name"}}}))
3031 {#Added
3032 if($ClassId{1}{$Class_Type{"Name"}} and not $ClassVirtFunc{1}{$Class_Type{"Name"}}{$VirtFuncName} and $AddedInt{$VirtFuncName})
3033 {
3034 if($CompleteSignature{2}{$VirtFuncName}{"VirtualRedefine"})
3035 {
3036 if($TargetFunction eq $VirtFuncName)
3037 {
3038 my $BaseClass_Id = $CompleteSignature{2}{$CompleteSignature{2}{$VirtFuncName}{"VirtualRedefine"}}{"Class"};
3039 my %BaseClass_Type = get_Type($Tid_TDid{2}{$BaseClass_Id}, $BaseClass_Id, 2);
3040 my $BaseClass_Name = $BaseClass_Type{"Name"};
3041 %{$CompatProblems{$TargetFunction}{"Virtual_Function_Redefinition"}{$tr_name{$CompleteSignature{2}{$VirtFuncName}{"VirtualRedefine"}}}}=(
3042 "Type_Name"=>$Class_Type{"Name"},
3043 "Type_Type"=>$Class_Type{"Type"},
3044 "Header"=>$CompleteSignature{2}{$TargetFunction}{"Header"},
3045 "Line"=>$CompleteSignature{2}{$TargetFunction}{"Line"},
3046 "Target"=>$tr_name{$CompleteSignature{2}{$VirtFuncName}{"VirtualRedefine"}},
3047 "Signature"=>$tr_name{$TargetFunction},
3048 "Old_Value"=>$tr_name{$CompleteSignature{2}{$VirtFuncName}{"VirtualRedefine"}},
3049 "New_Value"=>$tr_name{$TargetFunction},
3050 "Old_SoName"=>$Interface_Library{1}{$TargetFunction},
3051 "New_SoName"=>$Interface_Library{2}{$TargetFunction} );
3052 }
3053 }
3054 elsif($TargetFunction ne $VirtFuncName)
3055 {
3056 %{$CompatProblems{$TargetFunction}{"Added_Virtual_Function"}{$tr_name{$VirtFuncName}}}=(
3057 "Type_Name"=>$Class_Type{"Name"},
3058 "Type_Type"=>$Class_Type{"Type"},
3059 "Header"=>$Class_Type{"Header"},
3060 "Line"=>$Class_Type{"Line"},
3061 "Target"=>$tr_name{$VirtFuncName},
3062 "Signature"=>$tr_name{$TargetFunction},
3063 "Old_SoName"=>$Interface_Library{1}{$TargetFunction},
3064 "New_SoName"=>$Interface_Library{2}{$TargetFunction} );
3065 }
3066 }
3067 }
3068 foreach my $VirtFuncName (keys(%{$ClassVirtFunc{1}{$Class_Type{"Name"}}}))
3069 {#Withdrawn
3070 if($ClassId{2}{$Class_Type{"Name"}} and not $ClassVirtFunc{2}{$Class_Type{"Name"}}{$VirtFuncName} and $WithdrawnInt{$VirtFuncName})
3071 {
3072 if($CompleteSignature{1}{$VirtFuncName}{"VirtualRedefine"})
3073 {
3074 if($TargetFunction eq $VirtFuncName)
3075 {
3076 my $BaseClass_Id = $CompleteSignature{1}{$CompleteSignature{1}{$VirtFuncName}{"VirtualRedefine"}}{"Class"};
3077 my $BaseClass_Name = $TypeDescr{1}{$Tid_TDid{1}{$BaseClass_Id}}{$BaseClass_Id}{"Name"};
3078 %{$CompatProblems{$TargetFunction}{"Virtual_Function_Redefinition_B"}{$tr_name{$CompleteSignature{1}{$VirtFuncName}{"VirtualRedefine"}}}}=(
3079 "Type_Name"=>$Class_Type{"Name"},
3080 "Type_Type"=>$Class_Type{"Type"},
3081 "Header"=>$CompleteSignature{2}{$TargetFunction}{"Header"},
3082 "Line"=>$CompleteSignature{2}{$TargetFunction}{"Line"},
3083 "Target"=>$tr_name{$CompleteSignature{1}{$VirtFuncName}{"VirtualRedefine"}},
3084 "Signature"=>$tr_name{$TargetFunction},
3085 "Old_Value"=>$tr_name{$TargetFunction},
3086 "New_Value"=>$tr_name{$CompleteSignature{1}{$VirtFuncName}{"VirtualRedefine"}},
3087 "Old_SoName"=>$Interface_Library{1}{$TargetFunction},
3088 "New_SoName"=>$Interface_Library{2}{$TargetFunction} );
3089 }
3090 }
3091 else
3092 {
3093 %{$CompatProblems{$TargetFunction}{"Withdrawn_Virtual_Function"}{$tr_name{$VirtFuncName}}}=(
3094 "Type_Name"=>$Class_Type{"Name"},
3095 "Type_Type"=>$Class_Type{"Type"},
3096 "Header"=>$Class_Type{"Header"},
3097 "Line"=>$Class_Type{"Line"},
3098 "Target"=>$tr_name{$VirtFuncName},
3099 "Signature"=>$tr_name{$TargetFunction},
3100 "Old_SoName"=>$Interface_Library{1}{$TargetFunction},
3101 "New_SoName"=>$Interface_Library{2}{$TargetFunction} );
3102 }
3103 }
3104 }
3105 }
3106
3107 sub find_virtual_method_in_base_classes($$$)
3108 {
3109 my ($VirtFuncName, $Checked_ClassId, $LibVersion) = @_;
3110 foreach my $BaseClass_Id (keys(%{$TypeDescr{$LibVersion}{$Tid_TDid{$LibVersion}{$Checked_ClassId}}{$Checked_ClassId}{"BaseClass"}}))
3111 {
3112 my $VirtMethodInClass = find_virtual_method_in_class($VirtFuncName, $BaseClass_Id, $LibVersion);
3113 if($VirtMethodInClass)
3114 {
3115 return $VirtMethodInClass;
3116 }
3117 my $VirtMethodInBaseClasses = find_virtual_method_in_base_classes($VirtFuncName, $BaseClass_Id, $LibVersion);
3118 if($VirtMethodInBaseClasses)
3119 {
3120 return $VirtMethodInBaseClasses;
3121 }
3122 }
3123 return "";
3124 }
3125
3126 sub find_virtual_method_in_class($$$)
3127 {
3128 my ($VirtFuncName, $Checked_ClassId, $LibVersion) = @_;
3129 my $Suffix = getFuncSuffix($VirtFuncName, $LibVersion);
3130 foreach my $Checked_VirtFuncName (keys(%{$ClassIdVirtFunc{$LibVersion}{$Checked_ClassId}}))
3131 {
3132 if($Suffix eq getFuncSuffix($Checked_VirtFuncName, $LibVersion)
3133 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"})))
3134 {
3135 return $Checked_VirtFuncName;
3136 }
3137 }
3138 return "";
3139 }
3140
3141 sub getFuncSuffix($$)
3142 {
3143 my ($FuncName, $LibVersion) = @_;
3144 my $ClassId = $CompleteSignature{$LibVersion}{$FuncName}{"Class"};
3145 my $ClassName = $TypeDescr{$LibVersion}{$Tid_TDid{$LibVersion}{$ClassId}}{$ClassId}{"Name"};
3146 my $ShortName = $CompleteSignature{$LibVersion}{$FuncName}{"ShortName"};
3147 my $Suffix = $tr_name{$FuncName};
3148 $Suffix =~ s/\A$ClassName\:\:[~]*$ShortName[ ]*//g;
3149 return $Suffix;
3150 }
3151
3152 sub isRecurType($$$$)
3153 {
3154 foreach (@RecurTypes)
3155 {
3156 if($_->{"Tid1"} eq $_[0]
3157 and $_->{"TDid1"} eq $_[1]
3158 and $_->{"Tid2"} eq $_[2]
3159 and $_->{"TDid2"} eq $_[3])
3160 {
3161 return 1;
3162 }
3163 }
3164 return 0;
3165 }
3166
3167 sub find_MemberPair_Pos_byName($$)
3168 {
3169 my ($Member_Name, $Pair_Type) = @_;
3170 foreach my $MemberPair_Pos (sort keys(%{$Pair_Type->{"Memb"}}))
3171 {
3172 if($Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"} eq $Member_Name)
3173 {
3174 return $MemberPair_Pos;
3175 }
3176 }
3177 return "lost";
3178 }
3179
3180 sub getBitfieldSum($$)
3181 {
3182 my ($Member_Pos, $Pair_Type) = @_;
3183 my $BitfieldSum = 0;
3184 while($Member_Pos>-1)
3185 {
3186 return $BitfieldSum if(not $Pair_Type->{"Memb"}{$Member_Pos}{"bitfield"});
3187 $BitfieldSum += $Pair_Type->{"Memb"}{$Member_Pos}{"bitfield"};
3188 $Member_Pos -= 1;
3189 }
3190 return $BitfieldSum;
3191 }
3192
3193 sub find_MemberPair_Pos_byVal($$)
3194 {
3195 my ($Member_Value, $Pair_Type) = @_;
3196 foreach my $MemberPair_Pos (sort keys(%{$Pair_Type->{"Memb"}}))
3197 {
3198 if($Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value)
3199 {
3200 return $MemberPair_Pos;
3201 }
3202 }
3203 return "lost";
3204 }
3205
3206 my %Priority_Value=(
3207 "High"=>3,
3208 "Medium"=>2,
3209 "Low"=>1
3210 );
3211
3212 sub max_priority($$)
3213 {
3214 my ($Priority1, $Priority2) = @_;
3215 if(cmp_priority($Priority1, $Priority2))
3216 {
3217 return $Priority1;
3218 }
3219 else
3220 {
3221 return $Priority2;
3222 }
3223 }
3224
3225 sub cmp_priority($$)
3226 {
3227 my ($Priority1, $Priority2) = @_;
3228 return ($Priority_Value{$Priority1}>$Priority_Value{$Priority2});
3229 }
3230
3231 sub set_Problems_Priority()
3232 {
3233 foreach my $InterfaceName (sort keys(%CompatProblems))
3234 {
3235 foreach my $Kind (sort keys(%{$CompatProblems{$InterfaceName}}))
3236 {
3237 foreach my $Location (sort keys(%{$CompatProblems{$InterfaceName}{$Kind}}))
3238 {
3239 my $IsInTypeInternals = $CompatProblems{$InterfaceName}{$Kind}{$Location}{"IsInTypeInternals"};
3240 my $InitialType_Type = $CompatProblems{$InterfaceName}{$Kind}{$Location}{"InitialType_Type"};
3241 if($Kind eq "Function_Become_Static")
3242 {
3243 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "High";
3244 }
3245 elsif($Kind eq "Function_Become_NonStatic")
3246 {
3247 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "High";
3248 }
3249 elsif($Kind eq "Parameter_Type_And_Size")
3250 {
3251 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "High";
3252 }
3253 elsif($Kind eq "Parameter_Type")
3254 {
3255 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low";
3256 }
3257 elsif($Kind eq "Withdrawn_Parameter")
3258 {
3259 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Medium";
3260 }
3261 elsif($Kind eq "Added_Parameter")
3262 {
3263 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Medium";
3264 }
3265 elsif($Kind eq "Parameter_BaseType_And_Size")
3266 {
3267 if($InitialType_Type eq "Pointer")
3268 {
3269 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low";
3270 }
3271 else
3272 {
3273 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "High";
3274 }
3275 }
3276 elsif($Kind eq "Parameter_BaseType")
3277 {
3278 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low";
3279 }
3280 elsif($Kind eq "Parameter_PointerLevel")
3281 {
3282 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "High";
3283 }
3284 elsif($Kind eq "Return_Type_And_Size")
3285 {
3286 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Medium";
3287 }
3288 elsif($Kind eq "Return_Type")
3289 {
3290 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low";
3291 }
3292 elsif($Kind eq "Return_BaseType_And_Size")
3293 {
3294 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Medium";
3295 }
3296 elsif($Kind eq "Return_BaseType")
3297 {
3298 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low";
3299 }
3300 elsif($Kind eq "Return_PointerLevel")
3301 {
3302 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low";
3303 }
3304 if($Kind eq "Added_Virtual_Function")
3305 {
3306 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "High";
3307 }
3308 elsif($Kind eq "Withdrawn_Virtual_Function")
3309 {
3310 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "High";
3311 }
3312 elsif($Kind eq "Virtual_Function_Position")
3313 {
3314 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "High";
3315 }
3316 elsif($Kind eq "Virtual_Function_Redefinition")
3317 {
3318 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low";
3319 }
3320 elsif($Kind eq "Virtual_Function_Redefinition_B")
3321 {
3322 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low";
3323 }
3324 elsif($Kind eq "Size")
3325 {
3326 if(($InitialType_Type eq "Pointer") or ($InitialType_Type eq "Array"))
3327 {
3328 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low";
3329 }
3330 else
3331 {
3332 if($IsInTypeInternals)
3333 {
3334 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Medium";
3335 }
3336 else
3337 {
3338 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "High";
3339 }
3340 }
3341 }
3342 elsif($Kind eq "BaseType")
3343 {
3344 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low";
3345 }
3346 elsif($Kind eq "Added_Member_And_Size")
3347 {
3348 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low";
3349 }
3350 elsif($Kind eq "Added_Middle_Member_And_Size")
3351 {
3352 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Medium";
3353 }
3354 elsif($Kind eq "Withdrawn_Member_And_Size")
3355 {
3356 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Medium";
3357 }
3358 elsif($Kind eq "Withdrawn_Member")
3359 {
3360 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low";
3361 }
3362 elsif($Kind eq "Withdrawn_Middle_Member_And_Size")
3363 {
3364 if($IsInTypeInternals)
3365 {
3366 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Medium";
3367 }
3368 else
3369 {
3370 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "High";
3371 }
3372 }
3373 elsif($Kind eq "Withdrawn_Middle_Member")
3374 {
3375 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Medium";
3376 }
3377 elsif($Kind eq "Member_Rename")
3378 {
3379 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low";
3380 }
3381 elsif($Kind eq "Enum_Member_Value")
3382 {
3383 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Medium";
3384 }
3385 elsif($Kind eq "Enum_Member_Name")
3386 {
3387 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low";
3388 }
3389 elsif($Kind eq "Member_Type_And_Size")
3390 {
3391 if(($InitialType_Type eq "Pointer") or ($InitialType_Type eq "Array"))
3392 {
3393 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low";
3394 }
3395 else
3396 {
3397 if($IsInTypeInternals)
3398 {
3399 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low";
3400 }
3401 else
3402 {
3403 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "High";
3404 }
3405 }
3406 }
3407 elsif($Kind eq "Member_Type")
3408 {
3409 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low";
3410 }
3411 elsif($Kind eq "Member_BaseType_And_Size")
3412 {
3413 if(($InitialType_Type eq "Pointer") or ($InitialType_Type eq "Array"))
3414 {
3415 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low";
3416 }
3417 else
3418 {
3419 if($IsInTypeInternals)
3420 {
3421 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low";
3422 }
3423 else
3424 {
3425 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "High";
3426 }
3427 }
3428 }
3429 elsif($Kind eq "Member_BaseType")
3430 {
3431 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low";
3432 }
3433 elsif($Kind eq "Member_PointerLevel")
3434 {
3435 if(($InitialType_Type eq "Pointer") or ($InitialType_Type eq "Array"))
3436 {
3437 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low";
3438 }
3439 else
3440 {
3441 if($IsInTypeInternals)
3442 {
3443 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Low";
3444 }
3445 else
3446 {
3447 $CompatProblems{$InterfaceName}{$Kind}{$Location}{"Priority"} = "Medium";
3448 }
3449 }
3450 }
3451 }
3452 }
3453 }
3454 }
3455
3456 sub pushType($$$$)
3457 {
3458 my %TypeDescriptor=(
3459 "Tid1" => $_[0],
3460 "TDid1" => $_[1],
3461 "Tid2" => $_[2],
3462 "TDid2" => $_[3] );
3463 push(@RecurTypes, \%TypeDescriptor);
3464 }
3465
3466 sub mergeTypes($$$$)
3467 {
3468 my ($Type1_Id, $Type1_DId, $Type2_Id, $Type2_DId) = @_;
3469 my (%Sub_SubProblems, %SubProblems) = ();
3470 if((not $Type1_Id and not $Type1_DId) or (not $Type2_Id and not $Type2_DId))
3471 {#Not Empty Inputs Only
3472 return ();
3473 }
3474 if($Cache{"mergeTypes"}{$Type1_Id}{$Type1_DId}{$Type2_Id}{$Type2_DId})
3475 {#Already Merged
3476 return %{$Cache{"mergeTypes"}{$Type1_Id}{$Type1_DId}{$Type2_Id}{$Type2_DId}};
3477 }
3478 my %Type1 = get_Type($Type1_DId, $Type1_Id, 1);
3479 my %Type2 = get_Type($Type2_DId, $Type2_Id, 2);
3480 my %Type1_Pure = get_PureType($Type1_DId, $Type1_Id, 1);
3481 my %Type2_Pure = get_PureType($Type2_DId, $Type2_Id, 2);
3482 return () if(not $Type1_Pure{"Size"} or not $Type2_Pure{"Size"});
3483 if(isRecurType($Type1_Pure{"Tid"}, $Type1_Pure{"TDid"}, $Type2_Pure{"Tid"}, $Type2_Pure{"TDid"}))
3484 {#Recursive Declarations
3485 return ();
3486 }
3487 return if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
3488 return if($OpaqueTypes{1}{$Type1_Pure{"Name"}} or $OpaqueTypes{2}{$Type1_Pure{"Name"}} or $OpaqueTypes{1}{$Type1{"Name"}} or $OpaqueTypes{2}{$Type1{"Name"}});
3489
3490 my %Typedef_1 = goToFirst($Type1{"TDid"}, $Type1{"Tid"}, 1, "Typedef");
3491 my %Typedef_2 = goToFirst($Type2{"TDid"}, $Type2{"Tid"}, 2, "Typedef");
3492 if($Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef" and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
3493 {
3494 my %Base_1 = get_OneStep_BaseType($Typedef_1{"TDid"}, $Typedef_1{"Tid"}, 1);
3495 my %Base_2 = get_OneStep_BaseType($Typedef_2{"TDid"}, $Typedef_2{"Tid"}, 2);
3496 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
3497 and ($Base_1{"Name"} ne $Base_2{"Name"}))
3498 {
3499 %{$SubProblems{"BaseType"}{$Typedef_1{"Name"}}}=(
3500 "Type_Name"=>$Typedef_1{"Name"},
3501 "Type_Type"=>"Typedef",
3502 "Header"=>$Typedef_2{"Header"},
3503 "Line"=>$Typedef_2{"Line"},
3504 "Old_Value"=>$Base_1{"Name"},
3505 "New_Value"=>$Base_2{"Name"} );
3506 }
3507 }
3508
3509 if(($Type1_Pure{"Name"} ne $Type2_Pure{"Name"}) and ($Type1_Pure{"Type"} ne "Pointer") and $Type1_Pure{"Name"}!~/anon\-/)
3510 {#Different types
3511 return ();
3512 }
3513
3514 pushType($Type1_Pure{"Tid"}, $Type1_Pure{"TDid"}, $Type2_Pure{"Tid"}, $Type2_Pure{"TDid"});
3515 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}) and ($Type1_Pure{"Type"} =~ /Struct|Class|Union/))
3516 {#Check Size
3517 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
3518 {
3519 %{$SubProblems{"Size"}{$Type1_Pure{"Name"}}}=(
3520 "Type_Name"=>$Type1_Pure{"Name"},
3521 "Type_Type"=>$Type1_Pure{"Type"},
3522 "Header"=>$Type2_Pure{"Header"},
3523 "Line"=>$Type2_Pure{"Line"},
3524 "Old_Value"=>$Type1_Pure{"Size"},
3525 "New_Value"=>$Type2_Pure{"Size"} );
3526 }
3527 }
3528 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[ ]*\*/))
3529 {#Check "void *"
3530 pop(@RecurTypes);
3531 return ();
3532 }
3533 if($Type1_Pure{"BaseType"}{"Tid"} and $Type2_Pure{"BaseType"}{"Tid"})
3534 {#Check Base Types
3535 %Sub_SubProblems = &mergeTypes($Type1_Pure{"BaseType"}{"Tid"}, $Type1_Pure{"BaseType"}{"TDid"}, $Type2_Pure{"BaseType"}{"Tid"}, $Type2_Pure{"BaseType"}{"TDid"});
3536 foreach my $Sub_SubProblemType (keys(%Sub_SubProblems))
3537 {
3538 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems{$Sub_SubProblemType}}))
3539 {
3540 %{$SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}} = %{$Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}};
3541 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}{"InitialType_Type"} = $Type1_Pure{"Type"};
3542 }
3543 }
3544 }
3545 foreach my $Member_Pos (sort keys(%{$Type1_Pure{"Memb"}}))
3546 {#Check Members
3547 next if($Type1_Pure{"Memb"}{$Member_Pos}{"access"} eq "private");
3548 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
3549 next if(not $Member_Name);
3550 my $Member_Location = $Member_Name;
3551 my $MemberPair_Pos = find_MemberPair_Pos_byName($Member_Name, \%Type2_Pure);
3552 if(($MemberPair_Pos eq "lost") and (($Type2_Pure{"Type"} eq "Struct") or ($Type2_Pure{"Type"} eq "Class")))
3553 {#Withdrawn_Member
3554 if($Member_Pos > keys(%{$Type2_Pure{"Memb"}}) - 1)
3555 {
3556 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
3557 {
3558 %{$SubProblems{"Withdrawn_Member_And_Size"}{$Member_Name}}=(
3559 "Target"=>$Member_Name,
3560 "Type_Name"=>$Type1_Pure{"Name"},
3561 "Type_Type"=>$Type1_Pure{"Type"},
3562 "Header"=>$Type2_Pure{"Header"},
3563 "Line"=>$Type2_Pure{"Line"},
3564 "Old_Size"=>$Type1_Pure{"Size"},
3565 "New_Size"=>$Type2_Pure{"Size"} );
3566 }
3567 else
3568 {
3569 %{$SubProblems{"Withdrawn_Member"}{$Member_Name}}=(
3570 "Target"=>$Member_Name,
3571 "Type_Name"=>$Type1_Pure{"Name"},
3572 "Type_Type"=>$Type1_Pure{"Type"},
3573 "Header"=>$Type2_Pure{"Header"},
3574 "Line"=>$Type2_Pure{"Line"} );
3575 }
3576 next;
3577 }
3578 elsif($Member_Pos < keys(%{$Type1_Pure{"Memb"}}) - 1)
3579 {
3580 my $MemberType_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
3581 my %MemberType_Pure = get_PureType($Tid_TDid{1}{$MemberType_Id}, $MemberType_Id, 1);
3582 my $MemberStraightPairType_Id = $Type2_Pure{"Memb"}{$Member_Pos}{"type"};
3583 my %MemberStraightPairType_Pure = get_PureType($Tid_TDid{2}{$MemberStraightPairType_Id}, $MemberStraightPairType_Id, 2);
3584
3585 if(($MemberType_Pure{"Size"} eq $MemberStraightPairType_Pure{"Size"}) and find_MemberPair_Pos_byName($Type2_Pure{"Memb"}{$Member_Pos}{"name"}, \%Type1_Pure) eq "lost")
3586 {
3587 %{$SubProblems{"Member_Rename"}{$Member_Name}}=(
3588 "Target"=>$Member_Name,
3589 "Type_Name"=>$Type1_Pure{"Name"},
3590 "Type_Type"=>$Type1_Pure{"Type"},
3591 "Header"=>$Type2_Pure{"Header"},
3592 "Line"=>$Type2_Pure{"Line"},
3593 "Old_Value"=>$Type1_Pure{"Memb"}{$Member_Pos}{"name"},
3594 "New_Value"=>$Type2_Pure{"Memb"}{$Member_Pos}{"name"} );
3595 $MemberPair_Pos = $Member_Pos;
3596 }
3597 else
3598 {
3599 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"})
3600 {
3601 my $BitfieldSum = getBitfieldSum($Member_Pos-1, \%Type1_Pure)%($POINTER_SIZE*8);
3602 if($BitfieldSum and $BitfieldSum-$Type2_Pure{"Memb"}{$Member_Pos}{"bitfield"}>=0)
3603 {
3604 %{$SubProblems{"Withdrawn_Middle_Member"}{$Member_Name}}=(
3605 "Target"=>$Member_Name,
3606 "Type_Name"=>$Type1_Pure{"Name"},
3607 "Type_Type"=>$Type1_Pure{"Type"},
3608 "Header"=>$Type2_Pure{"Header"},
3609 "Line"=>$Type2_Pure{"Line"} );
3610 next;
3611 }
3612 }
3613 %{$SubProblems{"Withdrawn_Middle_Member_And_Size"}{$Member_Name}}=(
3614 "Target"=>$Member_Name,
3615 "Type_Name"=>$Type1_Pure{"Name"},
3616 "Type_Type"=>$Type1_Pure{"Type"},
3617 "Header"=>$Type2_Pure{"Header"},
3618 "Line"=>$Type2_Pure{"Line"} );
3619 next;
3620 }
3621 }
3622 }
3623 if($Type1_Pure{"Type"} eq "Enum")
3624 {
3625 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
3626 next if(not $Member_Value1);
3627 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
3628 if($MemberPair_Pos eq "lost")
3629 {
3630 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
3631 if($MemberPair_Pos ne "lost")
3632 {
3633 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
3634 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
3635 "Type_Name"=>$Type1_Pure{"Name"},
3636 "Type_Type"=>"Enum",
3637 "Header"=>$Type2_Pure{"Header"},
3638 "Line"=>$Type2_Pure{"Line"},
3639 "Old_Value"=>$Type1_Pure{"Memb"}{$Member_Pos}{"name"},
3640 "New_Value"=>$Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"} );
3641 }
3642 }
3643 else
3644 {
3645 if($Member_Value1 ne "" and $Member_Value2 ne "")
3646 {
3647 if($Member_Value1 ne $Member_Value2)
3648 {
3649 %{$SubProblems{"Enum_Member_Value"}{$Member_Name}}=(
3650 "Target"=>$Member_Name,
3651 "Type_Name"=>$Type1_Pure{"Name"},
3652 "Type_Type"=>"Enum",
3653 "Header"=>$Type2_Pure{"Header"},
3654 "Line"=>$Type2_Pure{"Line"},
3655 "Old_Value"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
3656 "New_Value"=>$Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"} );
3657 }
3658 }
3659 }
3660 next;
3661 }
3662 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
3663 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
3664 %Sub_SubProblems = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Member");
3665 foreach my $Sub_SubProblemType (keys(%Sub_SubProblems))
3666 {
3667 %{$SubProblems{$Sub_SubProblemType}{$Member_Name}}=(
3668 "Target"=>$Member_Name,
3669 "Member_Position"=>$Member_Pos,
3670 "Type_Name"=>$Type1_Pure{"Name"},
3671 "Type_Type"=>$Type1_Pure{"Type"},
3672 "Header"=>$Type2_Pure{"Header"},
3673 "Line"=>$Type2_Pure{"Line"});
3674 @{$SubProblems{$Sub_SubProblemType}{$Member_Name}}{keys(%{$Sub_SubProblems{$Sub_SubProblemType}})} = values %{$Sub_SubProblems{$Sub_SubProblemType}};
3675 }
3676 if($MemberType1_Id and $MemberType2_Id)
3677 {#checking member type change (replace)
3678 %Sub_SubProblems = &mergeTypes($MemberType1_Id, $Tid_TDid{1}{$MemberType1_Id}, $MemberType2_Id, $Tid_TDid{2}{$MemberType2_Id});
3679 foreach my $Sub_SubProblemType (keys(%Sub_SubProblems))
3680 {
3681 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems{$Sub_SubProblemType}}))
3682 {
3683 my $NewLocation = ($Sub_SubLocation)?$Member_Location."->".$Sub_SubLocation:$Member_Location;
3684 %{$SubProblems{$Sub_SubProblemType}{$NewLocation}}=(
3685 "IsInTypeInternals"=>"Yes");
3686 @{$SubProblems{$Sub_SubProblemType}{$NewLocation}}{keys(%{$Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}})} = values %{$Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}};
3687 if($Sub_SubLocation !~ /\-\>/)
3688 {
3689 $SubProblems{$Sub_SubProblemType}{$NewLocation}{"Member_Type_Name"} = get_TypeName($MemberType1_Id, 1);
3690 $SubProblems{$Sub_SubProblemType}{$NewLocation}{"Start_Type_Name"} = get_TypeName($MemberType1_Id, 1);
3691 }
3692 }
3693 }
3694 }
3695 }
3696 if(($Type2_Pure{"Type"} eq "Struct") or ($Type2_Pure{"Type"} eq "Class"))
3697 {
3698 foreach my $Member_Pos (sort keys(%{$Type2_Pure{"Memb"}}))
3699 {#checking added members
3700 next if(not $Type2_Pure{"Memb"}{$Member_Pos}{"name"});
3701 my $MemberPair_Pos = find_MemberPair_Pos_byName($Type2_Pure{"Memb"}{$Member_Pos}{"name"}, \%Type1_Pure);
3702 if($MemberPair_Pos eq "lost")
3703 {#Added_Member
3704 if($Member_Pos > keys(%{$Type1_Pure{"Memb"}}) - 1)
3705 {
3706 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
3707 {
3708 if($Type2_Pure{"Memb"}{$Member_Pos}{"bitfield"})
3709 {
3710 my $BitfieldSum = getBitfieldSum($Member_Pos-1, \%Type2_Pure)%($POINTER_SIZE*8);
3711 next if($BitfieldSum and $BitfieldSum<=$POINTER_SIZE*8-$Type2_Pure{"Memb"}{$Member_Pos}{"bitfield"});
3712 }
3713 %{$SubProblems{"Added_Member_And_Size"}{$Type2_Pure{"Memb"}{$Member_Pos}{"name"}}}=(
3714 "Target"=>$Type2_Pure{"Memb"}{$Member_Pos}{"name"},
3715 "Type_Name"=>$Type1_Pure{"Name"},
3716 "Type_Type"=>$Type1_Pure{"Type"},
3717 "Header"=>$Type2_Pure{"Header"},
3718 "Line"=>$Type2_Pure{"Line"} );
3719 }
3720 }
3721 else
3722 {
3723 my $MemberType_Id = $Type2_Pure{"Memb"}{$Member_Pos}{"type"};
3724 my $MemberType_DId = $Tid_TDid{2}{$MemberType_Id};
3725 my %MemberType_Pure = get_PureType($MemberType_DId, $MemberType_Id, 2);
3726
3727 my $MemberStraightPairType_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
3728 my %MemberStraightPairType_Pure = get_PureType($Tid_TDid{1}{$MemberStraightPairType_Id}, $MemberStraightPairType_Id, 1);
3729
3730 if(($MemberType_Pure{"Size"} eq $MemberStraightPairType_Pure{"Size"}) and find_MemberPair_Pos_byName($Type1_Pure{"Memb"}{$Member_Pos}{"name"}, \%Type2_Pure) eq "lost")
3731 {
3732 next if($Type1_Pure{"Memb"}{$Member_Pos}{"access"} eq "private");
3733 %{$SubProblems{"Member_Rename"}{$Type2_Pure{"Memb"}{$Member_Pos}{"name"}}}=(
3734 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"name"},
3735 "Type_Name"=>$Type1_Pure{"Name"},
3736 "Type_Type"=>$Type1_Pure{"Type"},
3737 "Header"=>$Type2_Pure{"Header"},
3738 "Line"=>$Type2_Pure{"Line"},
3739 "Old_Value"=>$Type1_Pure{"Memb"}{$Member_Pos}{"name"},
3740 "New_Value"=>$Type2_Pure{"Memb"}{$Member_Pos}{"name"} );
3741 }
3742 else
3743 {
3744 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
3745 {
3746 if($Type2_Pure{"Memb"}{$Member_Pos}{"bitfield"})
3747 {
3748 my $BitfieldSum = getBitfieldSum($Member_Pos-1, \%Type2_Pure)%($POINTER_SIZE*8);
3749 next if($BitfieldSum and $BitfieldSum<=$POINTER_SIZE*8-$Type2_Pure{"Memb"}{$Member_Pos}{"bitfield"});
3750 }
3751 %{$SubProblems{"Added_Middle_Member_And_Size"}{$Type2_Pure{"Memb"}{$Member_Pos}{"name"}}}=(
3752 "Target"=>$Type2_Pure{"Memb"}{$Member_Pos}{"name"},
3753 "Type_Name"=>$Type1_Pure{"Name"},
3754 "Type_Type"=>$Type1_Pure{"Type"},
3755 "Header"=>$Type2_Pure{"Header"},
3756 "Line"=>$Type2_Pure{"Line"} );
3757 }
3758 }
3759 }
3760 }
3761 }
3762 }
3763 %{$Cache{"mergeTypes"}{$Type1_Id}{$Type1_DId}{$Type2_Id}{$Type2_DId}} = %SubProblems;
3764 pop(@RecurTypes);
3765 return %SubProblems;
3766 }
3767
3768 sub get_TypeName($$)
3769 {
3770 my ($TypeId, $LibVersion) = @_;
3771 return $TypeDescr{$LibVersion}{$Tid_TDid{$LibVersion}{$TypeId}}{$TypeId}{"Name"};
3772 }
3773
3774 sub goToFirst($$$$)
3775 {
3776 my ($TypeDId, $TypeId, $LibVersion, $Type_Type) = @_;
3777 if(defined $Cache{"goToFirst"}{$TypeDId}{$TypeId}{$LibVersion}{$Type_Type})
3778 {
3779 return %{$Cache{"goToFirst"}{$TypeDId}{$TypeId}{$LibVersion}{$Type_Type}};
3780 }
3781 return () if(not $TypeDescr{$LibVersion}{$TypeDId}{$TypeId});
3782 my %Type = %{$TypeDescr{$LibVersion}{$TypeDId}{$TypeId}};
3783 return () if(not $Type{"Type"});
3784 if($Type{"Type"} ne $Type_Type)
3785 {
3786 return () if(not $Type{"BaseType"}{"TDid"} and not $Type{"BaseType"}{"Tid"});
3787 %Type = goToFirst($Type{"BaseType"}{"TDid"}, $Type{"BaseType"}{"Tid"}, $LibVersion, $Type_Type);
3788 }
3789 $Cache{"goToFirst"}{$TypeDId}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
3790 return %Type;
3791 }
3792
3793 my %TypeSpecAttributes = (
3794 "Ref" => 1,
3795 "Const" => 1,
3796 "Volatile" => 1,
3797 "Restrict" => 1,
3798 "Typedef" => 1
3799 );
3800
3801 sub get_PureType($$$)
3802 {
3803 my ($TypeDId, $TypeId, $LibVersion) = @_;
3804 return "" if(not $TypeId);
3805 if(defined $Cache{"get_PureType"}{$TypeDId}{$TypeId}{$LibVersion})
3806 {
3807 return %{$Cache{"get_PureType"}{$TypeDId}{$TypeId}{$LibVersion}};
3808 }
3809 return "" if(not $TypeDescr{$LibVersion}{$TypeDId}{$TypeId});
3810 my %Type = %{$TypeDescr{$LibVersion}{$TypeDId}{$TypeId}};
3811 if($Type{"Type"} =~ /Struct|Union|Typedef|Class|Enum/)
3812 {
3813 $CheckedTypes{$Type{"Name"}} = 1;
3814 }
3815 return %Type if(not $Type{"BaseType"}{"TDid"} and not $Type{"BaseType"}{"Tid"});
3816 if($TypeSpecAttributes{$Type{"Type"}})
3817 {
3818 %Type = get_PureType($Type{"BaseType"}{"TDid"}, $Type{"BaseType"}{"Tid"}, $LibVersion);
3819 }
3820 $Cache{"get_PureType"}{$TypeDId}{$TypeId}{$LibVersion} = \%Type;
3821 return %Type;
3822 }
3823
3824 sub get_PointerLevel($$$)
3825 {
3826 my ($TypeDId, $TypeId, $LibVersion) = @_;
3827 return "" if(not $TypeId);
3828 if(defined $Cache{"get_PointerLevel"}{$TypeDId}{$TypeId}{$LibVersion})
3829 {
3830 return $Cache{"get_PointerLevel"}{$TypeDId}{$TypeId}{$LibVersion};
3831 }
3832 return "" if(not $TypeDescr{$LibVersion}{$TypeDId}{$TypeId});
3833 my %Type = %{$TypeDescr{$LibVersion}{$TypeDId}{$TypeId}};
3834 return 0 if(not $Type{"BaseType"}{"TDid"} and not $Type{"BaseType"}{"Tid"});
3835 my $PointerLevel = 0;
3836 if($Type{"Type"} eq "Pointer")
3837 {
3838 $PointerLevel += 1;
3839 }
3840 $PointerLevel += get_PointerLevel($Type{"BaseType"}{"TDid"}, $Type{"BaseType"}{"Tid"}, $LibVersion);
3841 $Cache{"get_PointerLevel"}{$TypeDId}{$TypeId}{$LibVersion} = $PointerLevel;
3842 return $PointerLevel;
3843 }
3844
3845 sub get_BaseType($$$)
3846 {
3847 my ($TypeDId, $TypeId, $LibVersion) = @_;
3848 return "" if(not $TypeId);
3849 if(defined $Cache{"get_BaseType"}{$TypeDId}{$TypeId}{$LibVersion})
3850 {
3851 return %{$Cache{"get_BaseType"}{$TypeDId}{$TypeId}{$LibVersion}};
3852 }
3853 return "" if(not $TypeDescr{$LibVersion}{$TypeDId}{$TypeId});
3854 my %Type = %{$TypeDescr{$LibVersion}{$TypeDId}{$TypeId}};
3855 if($Type{"Type"} =~ /Struct|Union|Typedef|Class|Enum/)
3856 {
3857 $CheckedTypes{$Type{"Name"}} = 1;
3858 }
3859 return %Type if(not $Type{"BaseType"}{"TDid"} and not $Type{"BaseType"}{"Tid"});
3860 %Type = get_BaseType($Type{"BaseType"}{"TDid"}, $Type{"BaseType"}{"Tid"}, $LibVersion);
3861 $Cache{"get_BaseType"}{$TypeDId}{$TypeId}{$LibVersion} = \%Type;
3862 return %Type;
3863 }
3864
3865 sub get_OneStep_BaseType($$$)
3866 {
3867 my ($TypeDId, $TypeId, $LibVersion) = @_;
3868 return "" if(not $TypeId);
3869 return "" if(not $TypeDescr{$LibVersion}{$TypeDId}{$TypeId});
3870 my %Type = %{$TypeDescr{$LibVersion}{$TypeDId}{$TypeId}};
3871 return %Type if(not $Type{"BaseType"}{"TDid"} and not $Type{"BaseType"}{"Tid"});
3872 return get_Type($Type{"BaseType"}{"TDid"}, $Type{"BaseType"}{"Tid"}, $LibVersion);
3873 }
3874
3875 sub get_Type($$$)
3876 {
3877 my ($TypeDId, $TypeId, $LibVersion) = @_;
3878 return "" if(not $TypeId);
3879 return "" if(not $TypeDescr{$LibVersion}{$TypeDId}{$TypeId});
3880 return %{$TypeDescr{$LibVersion}{$TypeDId}{$TypeId}};
3881 }
3882
3883 sub mergeLibs()
3884 {
3885 foreach my $Interface (sort keys(%AddedInt))
3886 {#checking added interfaces
3887 next if($InternalInterfaces{1}{$Interface} or $InternalInterfaces{2}{$Interface});
3888 next if(defined $InterfacesListPath and not $InterfacesList{$Interface});
3889 next if(defined $AppPath and not $InterfacesList_App{$Interface});
3890 next if($FuncAttr{2}{$Interface}{"Private"});
3891 next if(not $FuncAttr{2}{$Interface}{"Header"});
3892 %{$CompatProblems{$Interface}{"Added_Interface"}{"SharedLibrary"}}=(
3893 "Header"=>$FuncAttr{2}{$Interface}{"Header"},
3894 "Line"=>$FuncAttr{2}{$Interface}{"Line"},
3895 "Signature"=>$FuncAttr{2}{$Interface}{"Signature"},
3896 "New_SoName"=>$Interface_Library{2}{$Interface} );
3897 }
3898 foreach my $Interface (sort keys(%WithdrawnInt))
3899 {#checking withdrawn interfaces
3900 next if($InternalInterfaces{1}{$Interface} or $InternalInterfaces{2}{$Interface});
3901 next if(defined $InterfacesListPath and not $InterfacesList{$Interface});
3902 next if(defined $AppPath and not $InterfacesList_App{$Interface});
3903 next if($FuncAttr{1}{$Interface}{"Private"});
3904 next if(not $FuncAttr{1}{$Interface}{"Header"});
3905 %{$CompatProblems{$Interface}{"Withdrawn_Interface"}{"SharedLibrary"}}=(
3906 "Header"=>$FuncAttr{1}{$Interface}{"Header"},
3907 "Line"=>$FuncAttr{1}{$Interface}{"Line"},
3908 "Signature"=>$FuncAttr{1}{$Interface}{"Signature"},
3909 "Old_SoName"=>$Interface_Library{1}{$Interface} );
3910 }
3911 }
3912
3913 sub mergeSignatures()
3914 {
3915 my %SubProblems = ();
3916
3917 prepareInterfaces(1);
3918 prepareInterfaces(2);
3919 %FuncDescr=();
3920
3921 initializeClassVirtFunc(1);
3922 initializeClassVirtFunc(2);
3923
3924 checkVirtFuncRedefinitions(1);
3925 checkVirtFuncRedefinitions(2);
3926
3927 setVirtFuncPositions(1);
3928 setVirtFuncPositions(2);
3929
3930 foreach my $Interface (sort keys(%AddedInt))
3931 {#collecting the attributes of added interfaces
3932 next if($CheckedInterfaces{$Interface});
3933 if($CompleteSignature{2}{$Interface})
3934 {
3935 if($CompleteSignature{2}{$Interface}{"Private"})
3936 {
3937 $FuncAttr{2}{$Interface}{"Private"} = 1;
3938 }
3939 if($CompleteSignature{2}{$Interface}{"Protected"})
3940 {
3941 $FuncAttr{2}{$Interface}{"Protected"} = 1;
3942 }
3943 if($CompleteSignature{2}{$Interface}{"Header"})
3944 {
3945 $FuncAttr{2}{$Interface}{"Header"} = $CompleteSignature{2}{$Interface}{"Header"};
3946 }
3947 if($CompleteSignature{2}{$Interface}{"Line"})
3948 {
3949 $FuncAttr{2}{$Interface}{"Line"} = $CompleteSignature{2}{$Interface}{"Line"};
3950 }
3951 $FuncAttr{2}{$Interface}{"Signature"} = get_Signature($Interface, 2);
3952 foreach my $ParamPos (keys(%{$CompleteSignature{2}{$Interface}{"Param"}}))
3953 {
3954 my $ParamType_Id = $CompleteSignature{2}{$Interface}{"Param"}{$ParamPos}{"type"};
3955 my $ParamType_DId = $Tid_TDid{2}{$ParamType_Id};
3956 my %ParamType = get_Type($ParamType_DId, $ParamType_Id, 2);
3957 }
3958 #checking virtual table
3959 check_VirtualTable($Interface, 2);
3960 $CheckedInterfaces{$Interface} = 1;
3961 }
3962 }
3963 foreach my $Interface (sort keys(%WithdrawnInt))
3964 {#collecting the attributes of withdrawn interfaces
3965 next if($CheckedInterfaces{$Interface});
3966 if($CompleteSignature{1}{$Interface})
3967 {
3968 if($CompleteSignature{1}{$Interface}{"Private"})
3969 {
3970 $FuncAttr{1}{$Interface}{"Private"} = 1;
3971 }
3972 if($CompleteSignature{1}{$Interface}{"Protected"})
3973 {
3974 $FuncAttr{1}{$Interface}{"Protected"} = 1;
3975 }
3976 if($CompleteSignature{1}{$Interface}{"Header"})
3977 {
3978 $FuncAttr{1}{$Interface}{"Header"} = $CompleteSignature{1}{$Interface}{"Header"};
3979 }
3980 if($CompleteSignature{1}{$Interface}{"Line"})
3981 {
3982 $FuncAttr{1}{$Interface}{"Line"} = $CompleteSignature{1}{$Interface}{"Line"};
3983 }
3984 $FuncAttr{1}{$Interface}{"Signature"} = get_Signature($Interface, 1);
3985 foreach my $ParamPos (keys(%{$CompleteSignature{1}{$Interface}{"Param"}}))
3986 {
3987 my $ParamType_Id = $CompleteSignature{1}{$Interface}{"Param"}{$ParamPos}{"type"};
3988 my $ParamType_DId = $Tid_TDid{1}{$ParamType_Id};
3989 my %ParamType = get_Type($ParamType_DId, $ParamType_Id, 1);
3990 }
3991 #checking virtual table
3992 check_VirtualTable($Interface, 1);
3993 $CheckedInterfaces{$Interface} = 1;
3994 }
3995 }
3996
3997 foreach my $Interface (sort keys(%{$CompleteSignature{1}}))
3998 {#checking interfaces
3999 if(($Interface !~ /\@/) and ($SymVer{1}{$Interface} =~ /\A(.*)[\@]+/))
4000 {
4001 next if($1 eq $Interface);
4002 }
4003 my ($MnglName, $SymbolVersion) = ($Interface, "");
4004 if($Interface =~ /\A([^@]+)[\@]+([^@]+)\Z/)
4005 {
4006 ($MnglName, $SymbolVersion) = ($1, $2);
4007 }
4008 next if($InternalInterfaces{1}{$Interface} or $InternalInterfaces{2}{$Interface});
4009 next if(defined $InterfacesListPath and not $InterfacesList{$Interface});
4010 next if(defined $AppPath and not $InterfacesList_App{$Interface});
4011 next if($CheckedInterfaces{$Interface});
4012 next if($CompleteSignature{1}{$Interface}{"Private"});
4013 next if(not $CompleteSignature{1}{$Interface}{"Header"} or not $CompleteSignature{2}{$Interface}{"Header"});
4014 next if(not $CompleteSignature{1}{$Interface}{"MnglName"} or not $CompleteSignature{2}{$Interface}{"MnglName"});
4015 next if((not $CompleteSignature{1}{$Interface}{"PureVirt"} and $CompleteSignature{2}{$Interface}{"PureVirt"}) or ($CompleteSignature{1}{$Interface}{"PureVirt"} and not $CompleteSignature{2}{$Interface}{"PureVirt"}));
4016 $CheckedInterfaces{$Interface} = 1;
4017 #checking virtual table
4018 check_VirtualTable($Interface, 1);
4019 #checking attributes
4020 if($CompleteSignature{2}{$Interface}{"Static"} and not $CompleteSignature{1}{$Interface}{"Static"})
4021 {
4022 %{$CompatProblems{$Interface}{"Function_Become_Static"}{"Attributes"}}=(
4023 "Header"=>$CompleteSignature{1}{$Interface}{"Header"},
4024 "Line"=>$CompleteSignature{1}{$Interface}{"Line"},
4025 "Signature"=>get_Signature($Interface, 1),
4026 "Old_SoName"=>$Interface_Library{1}{$Interface},
4027 "New_SoName"=>$Interface_Library{2}{$Interface} );
4028 }
4029 elsif(not $CompleteSignature{2}{$Interface}{"Static"} and $CompleteSignature{1}{$Interface}{"Static"})
4030 {
4031 %{$CompatProblems{$Interface}{"Function_Become_NonStatic"}{"Attributes"}}=(
4032 "Header"=>$CompleteSignature{1}{$Interface}{"Header"},
4033 "Line"=>$CompleteSignature{1}{$Interface}{"Line"},
4034 "Signature"=>get_Signature($Interface, 1),
4035 "Old_SoName"=>$Interface_Library{1}{$Interface},
4036 "New_SoName"=>$Interface_Library{2}{$Interface} );
4037 }
4038 if($CompleteSignature{1}{$Interface}{"Virt"} and $CompleteSignature{2}{$Interface}{"Virt"})
4039 {
4040 if($CompleteSignature{1}{$Interface}{"Position"}!=$CompleteSignature{2}{$Interface}{"Position"})
4041 {
4042 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
4043 my $Class_DId = $Tid_TDid{1}{$Class_Id};
4044 my %Class_Type = get_Type($Class_DId, $Class_Id, 1);
4045 %{$CompatProblems{$Interface}{"Virtual_Function_Position"}{$tr_name{$MnglName}}}=(
4046 "Type_Name"=>$Class_Type{"Name"},
4047 "Type_Type"=>$Class_Type{"Type"},
4048 "Header"=>$Class_Type{"Header"},
4049 "Line"=>$Class_Type{"Line"},
4050 "Old_Value"=>$CompleteSignature{1}{$Interface}{"Position"},
4051 "New_Value"=>$CompleteSignature{2}{$Interface}{"Position"},
4052 "Signature"=>get_Signature($Interface, 1),
4053 "Target"=>$tr_name{$MnglName},
4054 "Old_SoName"=>$Interface_Library{1}{$Interface},
4055 "New_SoName"=>$Interface_Library{2}{$Interface} );
4056 }
4057 }
4058 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$Interface}{"Param"}}))
4059 {#checking added parameters
4060 last if($Interface=~/\A_Z/);
4061 if(not defined $CompleteSignature{1}{$Interface}{"Param"}{$ParamPos})
4062 {#checking withdrawn parameters
4063 my $ParamType2_Id = $CompleteSignature{2}{$Interface}{"Param"}{$ParamPos}{"type"};
4064 my $Parameter_Name = $CompleteSignature{2}{$Interface}{"Param"}{$ParamPos}{"name"};
4065 last if(get_TypeName($ParamType2_Id, 2) eq "...");
4066 %{$CompatProblems{$Interface}{"Added_Parameter"}{num_to_str($ParamPos+1)." Parameter"}}=(
4067 "Target"=>$Parameter_Name,
4068 "Parameter_Position"=>$ParamPos,
4069 "Signature"=>get_Signature($Interface, 1),
4070 "Header"=>$CompleteSignature{1}{$Interface}{"Header"},
4071 "Line"=>$CompleteSignature{1}{$Interface}{"Line"},
4072 "Old_SoName"=>$Interface_Library{1}{$Interface},
4073 "New_SoName"=>$Interface_Library{2}{$Interface});
4074 }
4075 }
4076 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Interface}{"Param"}}))
4077 {#checking parameters
4078 my $ParamType1_Id = $CompleteSignature{1}{$Interface}{"Param"}{$ParamPos}{"type"};
4079 my $Parameter_Name = $CompleteSignature{1}{$Interface}{"Param"}{$ParamPos}{"name"};
4080 if(not defined $CompleteSignature{2}{$Interface}{"Param"}{$ParamPos} and get_TypeName($ParamType1_Id, 1) ne "..." and $Interface!~/\A_Z/)
4081 {#checking withdrawn parameters
4082 %{$CompatProblems{$Interface}{"Withdrawn_Parameter"}{num_to_str($ParamPos+1)." Parameter"}}=(
4083 "Target"=>$Parameter_Name,
4084 "Parameter_Position"=>$ParamPos,
4085 "Signature"=>get_Signature($Interface, 1),
4086 "Header"=>$CompleteSignature{1}{$Interface}{"Header"},
4087 "Line"=>$CompleteSignature{1}{$Interface}{"Line"},
4088 "Old_SoName"=>$Interface_Library{1}{$Interface},
4089 "New_SoName"=>$Interface_Library{2}{$Interface});
4090 next;
4091 }
4092 my $ParamType2_Id = $CompleteSignature{2}{$Interface}{"Param"}{$ParamPos}{"type"};
4093 next if(not $ParamType1_Id or not $ParamType2_Id);
4094 my $Parameter_Location = ($Parameter_Name)?$Parameter_Name:num_to_str($ParamPos+1)." Parameter";
4095
4096 #checking type change(replace)
4097 %SubProblems = detectTypeChange($ParamType1_Id, $ParamType2_Id, "Parameter");
4098 foreach my $SubProblemType (keys(%SubProblems))
4099 {
4100 %{$CompatProblems{$Interface}{$SubProblemType}{$Parameter_Location}}=(
4101 "Target"=>$Parameter_Name,
4102 "Parameter_Position"=>$ParamPos,
4103 "Signature"=>get_Signature($Interface, 1),
4104 "Header"=>$CompleteSignature{1}{$Interface}{"Header"},
4105 "Line"=>$CompleteSignature{1}{$Interface}{"Line"},
4106 "Old_SoName"=>$Interface_Library{1}{$Interface},
4107 "New_SoName"=>$Interface_Library{2}{$Interface});
4108 @{$CompatProblems{$Interface}{$SubProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
4109 }
4110 @RecurTypes = ();
4111 #checking type definition changes
4112 %SubProblems = mergeTypes($ParamType1_Id, $Tid_TDid{1}{$ParamType1_Id}, $ParamType2_Id, $Tid_TDid{2}{$ParamType2_Id});
4113 foreach my $SubProblemType (keys(%SubProblems))
4114 {
4115 foreach my $SubLocation (keys(%{$SubProblems{$SubProblemType}}))
4116 {
4117 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
4118 %{$CompatProblems{$Interface}{$SubProblemType}{$NewLocation}}=(
4119 "Signature"=>get_Signature($Interface, 1),
4120 "Header"=>$CompleteSignature{1}{$Interface}{"Header"},
4121 "Line"=>$CompleteSignature{1}{$Interface}{"Line"},
4122 "Old_SoName"=>$Interface_Library{1}{$Interface},
4123 "New_SoName"=>$Interface_Library{2}{$Interface},
4124 "Parameter_Type_Name"=>get_TypeName($ParamType1_Id, 1),
4125 "Parameter_Position"=>$ParamPos,
4126 "Parameter_Name"=>$Parameter_Name);
4127 @{$CompatProblems{$Interface}{$SubProblemType}{$NewLocation}}{keys(%{$SubProblems{$SubProblemType}{$SubLocation}})} = values %{$SubProblems{$SubProblemType}{$SubLocation}};
4128 if($SubLocation !~ /\-\>/)
4129 {
4130 $CompatProblems{$Interface}{$SubProblemType}{$NewLocation}{"Start_Type_Name"} = get_TypeName($ParamType1_Id, 1);
4131 }
4132 }
4133 }
4134 }
4135 #checking return type
4136 my $ReturnType1_Id = $CompleteSignature{1}{$Interface}{"Return"};
4137 my $ReturnType2_Id = $CompleteSignature{2}{$Interface}{"Return"};
4138 %SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return");
4139 foreach my $SubProblemType (keys(%SubProblems))
4140 {
4141 %{$CompatProblems{$Interface}{$SubProblemType}{"RetVal"}}=(
4142 "Signature"=>get_Signature($Interface, 1),
4143 "Header"=>$CompleteSignature{1}{$Interface}{"Header"},
4144 "Line"=>$CompleteSignature{1}{$Interface}{"Line"},
4145 "Old_SoName"=>$Interface_Library{1}{$Interface},
4146 "New_SoName"=>$Interface_Library{2}{$Interface});
4147 @{$CompatProblems{$Interface}{$SubProblemType}{"RetVal"}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
4148 }
4149 if($ReturnType1_Id and $ReturnType2_Id)
4150 {
4151 @RecurTypes = ();
4152 %SubProblems = mergeTypes($ReturnType1_Id, $Tid_TDid{1}{$ReturnType1_Id}, $ReturnType2_Id, $Tid_TDid{2}{$ReturnType2_Id});
4153 foreach my $SubProblemType (keys(%SubProblems))
4154 {
4155 foreach my $SubLocation (keys(%{$SubProblems{$SubProblemType}}))
4156 {
4157 my $NewLocation = ($SubLocation)?"RetVal->".$SubLocation:"RetVal";
4158 %{$CompatProblems{$Interface}{$SubProblemType}{$NewLocation}}=(
4159 "Signature"=>get_Signature($Interface, 1),
4160 "Header"=>$CompleteSignature{1}{$Interface}{"Header"},
4161 "Line"=>$CompleteSignature{1}{$Interface}{"Line"},
4162 "Old_SoName"=>$Interface_Library{1}{$Interface},
4163 "New_SoName"=>$Interface_Library{2}{$Interface},
4164 "Return_Type_Name"=>get_TypeName($ReturnType1_Id, 1) );
4165 @{$CompatProblems{$Interface}{$SubProblemType}{$NewLocation}}{keys(%{$SubProblems{$SubProblemType}{$SubLocation}})} = values %{$SubProblems{$SubProblemType}{$SubLocation}};
4166 if($SubLocation !~ /\-\>/)
4167 {
4168 $CompatProblems{$Interface}{$SubProblemType}{$NewLocation}{"Start_Type_Name"} = get_TypeName($ReturnType1_Id, 1);
4169 }
4170 }
4171 }
4172 }
4173
4174 #checking object type
4175 my $ObjectType1_Id = $CompleteSignature{1}{$Interface}{"Class"};
4176 my $ObjectType2_Id = $CompleteSignature{2}{$Interface}{"Class"};
4177 if($ObjectType1_Id and $ObjectType2_Id)
4178 {
4179 my $ThisType1_Id = getTypeIdByName(get_TypeName($ObjectType1_Id, 1)."*const", 1);
4180 my $ThisType2_Id = getTypeIdByName(get_TypeName($ObjectType2_Id, 2)."*const", 2);
4181 if($ThisType1_Id and $ThisType2_Id)
4182 {
4183 @RecurTypes = ();
4184 %SubProblems = mergeTypes($ThisType1_Id, $Tid_TDid{1}{$ThisType1_Id}, $ThisType2_Id, $Tid_TDid{2}{$ThisType2_Id});
4185 foreach my $SubProblemType (keys(%SubProblems))
4186 {
4187 foreach my $SubLocation (keys(%{$SubProblems{$SubProblemType}}))
4188 {
4189 my $NewLocation = ($SubLocation)?"Obj->".$SubLocation:"Obj";
4190 %{$CompatProblems{$Interface}{$SubProblemType}{$NewLocation}}=(
4191 "Signature"=>get_Signature($Interface, 1),
4192 "Header"=>$CompleteSignature{1}{$Interface}{"Header"},
4193 "Line"=>$CompleteSignature{1}{$Interface}{"Line"},
4194 "Old_SoName"=>$Interface_Library{1}{$Interface},
4195 "New_SoName"=>$Interface_Library{2}{$Interface},
4196 "Object_Type_Name"=>get_TypeName($ObjectType1_Id, 1) );
4197 @{$CompatProblems{$Interface}{$SubProblemType}{$NewLocation}}{keys(%{$SubProblems{$SubProblemType}{$SubLocation}})} = values %{$SubProblems{$SubProblemType}{$SubLocation}};
4198 if($SubLocation !~ /\-\>/)
4199 {
4200 $CompatProblems{$Interface}{$SubProblemType}{$NewLocation}{"Start_Type_Name"} = get_TypeName($ObjectType1_Id, 1);
4201 }
4202 }
4203 }
4204 }
4205 }
4206 }
4207 set_Problems_Priority();
4208 }
4209
4210 sub getTypeIdByName($$)
4211 {
4212 my ($TypeName, $Version) = @_;
4213 return $TName_Tid{$Version}{correctName($TypeName)};
4214 }
4215
4216 sub detectTypeChange($$$)
4217 {
4218 my ($Type1_Id, $Type2_Id, $Prefix) = @_;
4219 my %LocalProblems = ();
4220 my $Type1_DId = $Tid_TDid{1}{$Type1_Id};
4221 my $Type2_DId = $Tid_TDid{2}{$Type2_Id};
4222 my %Type1 = get_Type($Type1_DId, $Type1_Id, 1);
4223 my %Type2 = get_Type($Type2_DId, $Type2_Id, 2);
4224 my %Type1_Base = get_BaseType($Type1_DId, $Type1_Id, 1);
4225 my %Type2_Base = get_BaseType($Type2_DId, $Type2_Id, 2);
4226 my %Type1_Pure = get_PureType($Type1_DId, $Type1_Id, 1);
4227 my %Type2_Pure = get_PureType($Type2_DId, $Type2_Id, 2);
4228 my $Type1_PointerLevel = get_PointerLevel($Type1_DId, $Type1_Id, 1);
4229 my $Type2_PointerLevel = get_PointerLevel($Type2_DId, $Type2_Id, 2);
4230 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 "");
4231 if($Type1_Base{"Name"} ne $Type2_Base{"Name"})
4232 {#base type change
4233 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
4234 {
4235 if($Type1_Base{"Size"}!=$Type2_Base{"Size"})
4236 {
4237 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
4238 "Old_Value"=>$Type1_Base{"Name"},
4239 "New_Value"=>$Type2_Base{"Name"},
4240 "Old_Size"=>$Type1_Base{"Size"},
4241 "New_Size"=>$Type2_Base{"Size"},
4242 "InitialType_Type"=>$Type1_Pure{"Type"});
4243 }
4244 else
4245 {
4246 %{$LocalProblems{$Prefix."_BaseType"}}=(
4247 "Old_Value"=>$Type1_Base{"Name"},
4248 "New_Value"=>$Type2_Base{"Name"},
4249 "InitialType_Type"=>$Type1_Pure{"Type"});
4250 }
4251 }
4252 }
4253 elsif($Type1{"Name"} ne $Type2{"Name"})
4254 {#type change
4255 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
4256 {
4257 if($Type1{"Size"}!=$Type2{"Size"})
4258 {
4259 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
4260 "Old_Value"=>$Type1{"Name"},
4261 "New_Value"=>$Type2{"Name"},
4262 "Old_Size"=>($Type1{"Type"} eq "Array")?$Type1{"Size"}*$Type1_Base{"Size"}:$Type1{"Size"},
4263 "New_Size"=>($Type2{"Type"} eq "Array")?$Type2{"Size"}*$Type2_Base{"Size"}:$Type2{"Size"},
4264 "InitialType_Type"=>$Type1_Pure{"Type"});
4265 }
4266 else
4267 {
4268 %{$LocalProblems{$Prefix."_Type"}}=(
4269 "Old_Value"=>$Type1{"Name"},
4270 "New_Value"=>$Type2{"Name"},
4271 "InitialType_Type"=>$Type1_Pure{"Type"});
4272 }
4273 }
4274 }
4275
4276 if($Type1_PointerLevel!=$Type2_PointerLevel)
4277 {
4278 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
4279 "Old_Value"=>$Type1_PointerLevel,
4280 "New_Value"=>$Type2_PointerLevel);
4281 }
4282 return %LocalProblems;
4283 }
4284
4285 sub htmlSpecChars($)
4286 {
4287 my $Str = $_[0];
4288 $Str =~ s/\&([^#])/&amp;$1/g;
4289 $Str =~ s/</&lt;/g;
4290 $Str =~ s/>/&gt;/g;
4291 $Str =~ s/([^ ])( )([^ ])/$1\@ALONE_SP\@$3/g;
4292 $Str =~ s/ /&nbsp;/g;
4293 $Str =~ s/\@ALONE_SP\@/ /g;
4294 $Str =~ s/\n/<br\/>/g;
4295 return $Str;
4296 }
4297
4298 sub highLight_Signature($)
4299 {
4300 my $Signature = $_[0];
4301 return highLight_Signature_PPos_Italic($Signature, "", 0, 0);
4302 }
4303
4304 sub highLight_Signature_Italic($)
4305 {
4306 my $Signature = $_[0];
4307 return highLight_Signature_PPos_Italic($Signature, "", 1, 0);
4308 }
4309
4310 sub highLight_Signature_Italic_Color($)
4311 {
4312 my $Signature = $_[0];
4313 return highLight_Signature_PPos_Italic($Signature, "", 1, 1);
4314 }
4315
4316 sub highLight_Signature_PPos_Italic($$$$)
4317 {
4318 my ($FullSignature, $Parameter_Position, $ItalicParams, $ColorParams) = @_;
4319 my ($Signature, $SymbolVersion) = ($FullSignature, "");
4320 if($FullSignature =~ /\A(.+)[\@]+(.+)\Z/)
4321 {
4322 ($Signature, $SymbolVersion) = ($1, $2);
4323 }
4324 if($Signature=~/\Atypeinfo\W/)
4325 {
4326 return $Signature.(($SymbolVersion)?"<span class='symver'> \@ $SymbolVersion</span>":"");
4327 }
4328 if($Signature!~/\)(| const)\Z/)
4329 {
4330 return $Signature.(($SymbolVersion)?"<span class='symver'> \@ $SymbolVersion</span>":"");
4331 }
4332 $Signature =~ /(.+?)\(.*\)(| const)\Z/;
4333 my ($Begin, $End) = ($1, $2);
4334 my @Parts = ();
4335 my $Part_Num = 0;
4336 foreach my $Part (get_Signature_Parts($Signature, 1))
4337 {
4338 $Part =~ s/\A\s+|\s+\Z//g;
4339 my ($Part_Styled, $ParamName) = ($Part, "");
4340 if($Part=~/\([\*]+(\w+)\)/i)
4341 {#func-ptr
4342 $ParamName = $1;
4343 }
4344 elsif($Part=~/(\w+)[\,\)]*\Z/i)
4345 {
4346 $ParamName = $1;
4347 }
4348 if(not $ParamName)
4349 {
4350 push(@Parts, $Part);
4351 next;
4352 }
4353 if($ItalicParams and not $TName_Tid{1}{$Part} and not $TName_Tid{2}{$Part})
4354 {
4355 if(($Parameter_Position ne "") and ($Part_Num == $Parameter_Position))
4356 {
4357 $Part_Styled =~ s!(\W)$ParamName([\,\)]|\Z)!$1<span class='focus_param'>$ParamName</span>$2!ig;
4358 }
4359 elsif($ColorParams)
4360 {
4361 $Part_Styled =~ s!(\W)$ParamName([\,\)]|\Z)!$1<span class='color_param'>$ParamName</span>$2!ig;
4362 }
4363 else
4364 {
4365 $Part_Styled =~ s!(\W)$ParamName([\,\)]|\Z)!$1<span style='font-style:italic;'>$ParamName</span>$2!ig;
4366 }
4367 }
4368 $Part_Styled = "<span style='white-space:nowrap;'>".$Part_Styled."</span>";
4369 push(@Parts, $Part_Styled);
4370 $Part_Num += 1;
4371 }
4372 $Signature = $Begin."<span class='int_p'>"."(".join(" ", @Parts).")"."</span>".$End;
4373 $Signature =~ s!\[\]![<span style='padding-left:2px;'>]</span>!g;
4374 $Signature =~ s!operator=!operator<span style='padding-left:2px'>=</span>!g;
4375 $Signature =~ s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\])!<span style='color:Black;font-weight:normal;'>$1</span>!g;
4376 return $Signature.(($SymbolVersion)?"<span class='symver'> \@ $SymbolVersion</span>":"");
4377 }
4378
4379 sub get_Signature_Parts($$)
4380 {
4381 my ($Signature, $Comma) = @_;
4382 my @Parts = ();
4383 my $Bracket_Num = 0;
4384 my $Bracket2_Num = 0;
4385 my $Parameters = $Signature;
4386 if($Signature=~/&gt;|&lt;/)
4387 {
4388 $Parameters=~s/&gt;/>/g;
4389 $Parameters=~s/&lt;/</g;
4390 }
4391 my $Part_Num = 0;
4392 if($Parameters =~ s/.+?\((.*)\)(| const)\Z/$1/)
4393 {
4394 foreach my $Pos (0 .. length($Parameters) - 1)
4395 {
4396 my $Symbol = substr($Parameters, $Pos, 1);
4397 $Bracket_Num += 1 if($Symbol eq "(");
4398 $Bracket_Num -= 1 if($Symbol eq ")");
4399 $Bracket2_Num += 1 if($Symbol eq "<");
4400 $Bracket2_Num -= 1 if($Symbol eq ">");
4401 if($Symbol eq "," and $Bracket_Num==0 and $Bracket2_Num==0)
4402 {
4403 $Parts[$Part_Num] .= $Symbol if($Comma);
4404 $Part_Num += 1;
4405 }
4406 else
4407 {
4408 $Parts[$Part_Num] .= $Symbol;
4409 }
4410 }
4411 if($Signature=~/&gt;|&lt;/)
4412 {
4413 foreach my $Part (@Parts)
4414 {
4415 $Part=~s/\>/&gt;/g;
4416 $Part=~s/\</&lt;/g;
4417 }
4418 }
4419 return @Parts;
4420 }
4421 else
4422 {
4423 return ();
4424 }
4425 }
4426
4427 my %TypeProblems_Kind=(
4428 "Added_Virtual_Function"=>1,
4429 "Withdrawn_Virtual_Function"=>1,
4430 "Virtual_Function_Position"=>1,
4431 "Virtual_Function_Redefinition"=>1,
4432 "Virtual_Function_Redefinition_B"=>1,
4433 "Size"=>1,
4434 "Added_Member_And_Size"=>1,
4435 "Added_Middle_Member_And_Size"=>1,
4436 "Withdrawn_Member_And_Size"=>1,
4437 "Withdrawn_Member"=>1,
4438 "Withdrawn_Middle_Member_And_Size"=>1,
4439 "Member_Rename"=>1,
4440 "Enum_Member_Value"=>1,
4441 "Enum_Member_Name"=>1,
4442 "Member_Type_And_Size"=>1,
4443 "Member_Type"=>1,
4444 "Member_BaseType_And_Size"=>1,
4445 "Member_BaseType"=>1,
4446 "Member_PointerLevel"=>1,
4447 "BaseType"=>1
4448 );
4449
4450 my %InterfaceProblems_Kind=(
4451 "Added_Interface"=>1,
4452 "Withdrawn_Interface"=>1,
4453 "Function_Become_Static"=>1,
4454 "Function_Become_NonStatic"=>1,
4455 "Parameter_Type_And_Size"=>1,
4456 "Parameter_Type"=>1,
4457 "Parameter_BaseType_And_Size"=>1,
4458 "Parameter_BaseType"=>1,
4459 "Parameter_PointerLevel"=>1,
4460 "Return_Type_And_Size"=>1,
4461 "Return_Type"=>1,
4462 "Return_BaseType_And_Size"=>1,
4463 "Return_BaseType"=>1,
4464 "Return_PointerLevel"=>1,
4465 "Withdrawn_Parameter"=>1,
4466 "Added_Parameter"=>1
4467 );
4468
4469 sub testSystem_cpp()
4470 {
4471 print "testing for C++ library changes\n";
4472 my (@DataDefs_v1, @Sources_v1, @DataDefs_v2, @Sources_v2) = ();
4473
4474 #Withdrawn_Parameter
4475 @DataDefs_v1 = (@DataDefs_v1, "int func_withdrawn_parameter(int param, int withdrawn_param);");
4476 @Sources_v1 = (@Sources_v1, "int func_withdrawn_parameter(int param, int withdrawn_param)\n{\n return 0;\n}");
4477
4478 @DataDefs_v2 = (@DataDefs_v2, "int func_withdrawn_parameter(int param);");
4479 @Sources_v2 = (@Sources_v2, "int func_withdrawn_parameter(int param)\n{\n return 0;\n}");
4480
4481 #Added_Parameter
4482 @DataDefs_v1 = (@DataDefs_v1, "int func_added_parameter(int param);");
4483 @Sources_v1 = (@Sources_v1, "int func_added_parameter(int param)\n{\n return 0;\n}");
4484
4485 @DataDefs_v2 = (@DataDefs_v2, "int func_added_parameter(int param, int added_param);");
4486 @Sources_v2 = (@Sources_v2, "int func_added_parameter(int param, int added_param)\n{\n return 0;\n}");
4487
4488 #Added_Virtual_Function
4489 @DataDefs_v1 = (@DataDefs_v1, "class type_test_added_virtual_function\n{\npublic:\n int func1(int param);\n virtual int func2(int param);\n};");
4490 @Sources_v1 = (@Sources_v1, "int type_test_added_virtual_function::func1(int param)\n{\n return param;\n}");
4491 @Sources_v1 = (@Sources_v1, "int type_test_added_virtual_function::func2(int param)\n{\n return param;\n}");
4492
4493 @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};");
4494 @Sources_v2 = (@Sources_v2, "int type_test_added_virtual_function::func1(int param)\n{\n return param;\n}");
4495 @Sources_v2 = (@Sources_v2, "int type_test_added_virtual_function::func2(int param)\n{\n return param;\n}");
4496
4497 #added simple function
4498 @DataDefs_v2 = (@DataDefs_v2, "typedef int (*FUNCPTR_TYPE)(int a, int b);\nint added_function_param_funcptr(FUNCPTR_TYPE*const** f);");
4499 @Sources_v2 = (@Sources_v2, "int added_function_param_funcptr(FUNCPTR_TYPE*const** f)\n{\n return 0;\n}");
4500
4501 #Withdrawn_Virtual_Function
4502 @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};");
4503 @Sources_v1 = (@Sources_v1, "int type_test_withdrawn_virtual_function::func1(int param)\n{\n return param;\n}");
4504 @Sources_v1 = (@Sources_v1, "int type_test_withdrawn_virtual_function::func2(int param)\n{\n return param;\n}");
4505
4506 @DataDefs_v2 = (@DataDefs_v2, "class type_test_withdrawn_virtual_function\n{\npublic:\n int func1(int param);\n virtual int func2(int param);\n};");
4507 @Sources_v2 = (@Sources_v2, "int type_test_withdrawn_virtual_function::func1(int param)\n{\n return param;\n}");
4508 @Sources_v2 = (@Sources_v2, "int type_test_withdrawn_virtual_function::func2(int param)\n{\n return param;\n}");
4509
4510 #Virtual_Function_Position
4511 @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};");
4512 @Sources_v1 = (@Sources_v1, "int type_test_virtual_function_position::func1(int param)\n{\n return param;\n}");
4513 @Sources_v1 = (@Sources_v1, "int type_test_virtual_function_position::func2(int param)\n{\n return param;\n}");
4514
4515 @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};");
4516 @Sources_v2 = (@Sources_v2, "int type_test_virtual_function_position::func1(int param)\n{\n return param;\n}");
4517 @Sources_v2 = (@Sources_v2, "int type_test_virtual_function_position::func2(int param)\n{\n return param;\n}");
4518
4519 #virtual functions safe replace
4520 @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};");
4521 @Sources_v1 = (@Sources_v1, "int type_test_virtual_function_position_safe_replace_base::func1(int param)\n{\n return param;\n}");
4522 @Sources_v1 = (@Sources_v1, "int type_test_virtual_function_position_safe_replace_base::func2(int param)\n{\n return param;\n}");
4523
4524 @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};");
4525 @Sources_v2 = (@Sources_v2, "int type_test_virtual_function_position_safe_replace_base::func1(int param)\n{\n return param;\n}");
4526 @Sources_v2 = (@Sources_v2, "int type_test_virtual_function_position_safe_replace_base::func2(int param)\n{\n return param;\n}");
4527
4528 @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};");
4529 @Sources_v1 = (@Sources_v1, "int type_test_virtual_function_position_safe_replace::func1(int param)\n{\n return param;\n}");
4530 @Sources_v1 = (@Sources_v1, "int type_test_virtual_function_position_safe_replace::func2(int param)\n{\n return param;\n}");
4531
4532 @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};");
4533 @Sources_v2 = (@Sources_v2, "int type_test_virtual_function_position_safe_replace::func1(int param)\n{\n return param;\n}");
4534 @Sources_v2 = (@Sources_v2, "int type_test_virtual_function_position_safe_replace::func2(int param)\n{\n return param;\n}");
4535
4536 #virtual table changes
4537 @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};");
4538 @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};");
4539 @Sources_v1 = (@Sources_v1, "int type_test_virtual_table_base::func1(int param)\n{\n return param;\n}");
4540 @Sources_v1 = (@Sources_v1, "int type_test_virtual_table_base::func2(int param)\n{\n return param;\n}");
4541 @Sources_v1 = (@Sources_v1, "int type_test_virtual_table::func1(int param)\n{\n return param;\n}");
4542 @Sources_v1 = (@Sources_v1, "int type_test_virtual_table::func2(int param)\n{\n return param;\n}");
4543
4544 @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};");
4545 @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};");
4546 @Sources_v2 = (@Sources_v2, "int type_test_virtual_table_base::func1(int param)\n{\n return param;\n}");
4547 @Sources_v2 = (@Sources_v2, "int type_test_virtual_table_base::func2(int param)\n{\n return param;\n}");
4548 @Sources_v2 = (@Sources_v2, "int type_test_virtual_table::func1(int param)\n{\n return param;\n}");
4549 @Sources_v2 = (@Sources_v2, "int type_test_virtual_table::func2(int param)\n{\n return param;\n}");
4550
4551 #Virtual_Function_Redefinition
4552 @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};");
4553 @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};");
4554 @Sources_v1 = (@Sources_v1, "int type_test_virtual_function_redefinition_base::func1(int param)\n{\n return param;\n}");
4555 @Sources_v1 = (@Sources_v1, "int type_test_virtual_function_redefinition_base::func2(int param)\n{\n return param;\n}");
4556 @Sources_v1 = (@Sources_v1, "int type_test_virtual_function_redefinition::func3(int param)\n{\n return param;\n}");
4557
4558 @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};");
4559 @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};");
4560 @Sources_v2 = (@Sources_v2, "int type_test_virtual_function_redefinition_base::func1(int param){\n return param;\n}");
4561 @Sources_v2 = (@Sources_v2, "int type_test_virtual_function_redefinition_base::func2(int param){\n return param;\n}");
4562 @Sources_v2 = (@Sources_v2, "int type_test_virtual_function_redefinition::func2(int param)\n{\n return param;\n}");
4563 @Sources_v2 = (@Sources_v2, "int type_test_virtual_function_redefinition::func3(int param)\n{\n return param;\n}");
4564
4565 #size change
4566 @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};");
4567 @Sources_v1 = (@Sources_v1, "type_test_size type_test_size::func1(type_test_size param)\n{\n return param;\n}");
4568
4569 @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};");
4570 @Sources_v2 = (@Sources_v2, "type_test_size type_test_size::func1(type_test_size param)\n{\n return param;\n}");
4571
4572 #Added_Member_And_Size
4573 @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};");
4574 @Sources_v1 = (@Sources_v1, "type_test_added_member type_test_added_member::func1(type_test_added_member param)\n{\n return param;\n}");
4575
4576 @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};");
4577 @Sources_v2 = (@Sources_v2, "type_test_added_member type_test_added_member::func1(type_test_added_member param)\n{\n return param;\n}");
4578
4579 #Method object changes
4580 @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};");
4581 @Sources_v1 = (@Sources_v1, "int type_test_object_added_member::func1(int param)\n{\n return param;\n}");
4582
4583 @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};");
4584 @Sources_v2 = (@Sources_v2, "int type_test_object_added_member::func1(int param)\n{\n return param;\n}");
4585
4586 #added bitfield
4587 @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};");
4588 @Sources_v1 = (@Sources_v1, "type_test_added_bitfield type_test_added_bitfield::func1(type_test_added_bitfield param)\n{\n return param;\n}");
4589
4590 @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};");
4591 @Sources_v2 = (@Sources_v2, "type_test_added_bitfield type_test_added_bitfield::func1(type_test_added_bitfield param)\n{\n return param;\n}");
4592
4593 #withdrawn bitfield
4594 @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};");
4595 @Sources_v1 = (@Sources_v1, "type_test_withdrawn_bitfield type_test_withdrawn_bitfield::func1(type_test_withdrawn_bitfield param)\n{\n return param;\n}");
4596
4597 @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};");
4598 @Sources_v2 = (@Sources_v2, "type_test_withdrawn_bitfield type_test_withdrawn_bitfield::func1(type_test_withdrawn_bitfield param)\n{\n return param;\n}");
4599
4600 #Added_Middle_Member_And_Size
4601 @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};");
4602 @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}");
4603
4604 @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};");
4605 @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}");
4606
4607 #Member_Rename
4608 @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};");
4609 @Sources_v1 = (@Sources_v1, "type_test_member_rename type_test_member_rename::func1(type_test_member_rename param)\n{\n return param;\n}");
4610
4611 @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};");
4612 @Sources_v2 = (@Sources_v2, "type_test_member_rename type_test_member_rename::func1(type_test_member_rename param)\n{\n return param;\n}");
4613
4614 #Withdrawn_Member_And_Size
4615 @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};");
4616 @Sources_v1 = (@Sources_v1, "type_test_withdrawn_member type_test_withdrawn_member::func1(type_test_withdrawn_member param)\n{\n return param;\n}");
4617
4618 @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};");
4619 @Sources_v2 = (@Sources_v2, "type_test_withdrawn_member type_test_withdrawn_member::func1(type_test_withdrawn_member param)\n{\n return param;\n}");
4620
4621 #Withdrawn_Middle_Member_And_Size
4622 @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};");
4623 @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}");
4624
4625 @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};");
4626 @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}");
4627
4628 #Enum_Member_Value
4629 @DataDefs_v1 = (@DataDefs_v1, "enum type_test_enum_member_value_change\n{\n MEMBER_1=1,\n MEMBER_2=2\n};");
4630 @DataDefs_v1 = (@DataDefs_v1, "int func_test_enum_member_value_change(enum type_test_enum_member_value_change param);");
4631 @Sources_v1 = (@Sources_v1,
4632 "int func_test_enum_member_value_change(enum type_test_enum_member_value_change param)
4633 {
4634 switch(param)
4635 {
4636 case 1:
4637 return 1;
4638 case 2:
4639 return 2;
4640 }
4641 return 0;
4642 }");
4643
4644 @DataDefs_v2 = (@DataDefs_v2, "enum type_test_enum_member_value_change\n{\n MEMBER_1=2,\n MEMBER_2=1\n};");
4645 @DataDefs_v2 = (@DataDefs_v2, "int func_test_enum_member_value_change(enum type_test_enum_member_value_change param);");
4646 @Sources_v2 = (@Sources_v2,
4647 "int func_test_enum_member_value_change(enum type_test_enum_member_value_change param)
4648 {
4649 switch(param)
4650 {
4651 case 1:
4652 return 1;
4653 case 2:
4654 return 2;
4655 }
4656 return 0;
4657 }");
4658
4659 #Enum_Member_Name
4660 @DataDefs_v1 = (@DataDefs_v1, "enum type_test_enum_member_rename\n{\n BRANCH_1=1,\n BRANCH_2=2\n};");
4661 @DataDefs_v1 = (@DataDefs_v1, "int func_test_enum_member_rename(enum type_test_enum_member_rename param);");
4662 @Sources_v1 = (@Sources_v1,
4663 "int func_test_enum_member_rename(enum type_test_enum_member_rename param)
4664 {
4665 switch(param)
4666 {
4667 case 1:
4668 return 1;
4669 case 2:
4670 return 2;
4671 }
4672 return 0;
4673 }");
4674
4675 @DataDefs_v2 = (@DataDefs_v2, "enum type_test_enum_member_rename\n{\n BRANCH_FIRST=1,\n BRANCH_SECOND=1\n};");
4676 @DataDefs_v2 = (@DataDefs_v2, "int func_test_enum_member_rename(enum type_test_enum_member_rename param);");
4677 @Sources_v2 = (@Sources_v2,
4678 "int func_test_enum_member_rename(enum type_test_enum_member_rename param)
4679 {
4680 switch(param)
4681 {
4682 case 1:
4683 return 1;
4684 case 2:
4685 return 2;
4686 }
4687 return 0;
4688 }");
4689
4690 #Member_Type_And_Size
4691 @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};");
4692 @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}");
4693
4694 @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};");
4695 @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}");
4696
4697 #Member_Type
4698 @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};");
4699 @Sources_v1 = (@Sources_v1, "type_test_member_type type_test_member_type::func1(type_test_member_type param)\n{\n return param;\n}");
4700
4701 @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};");
4702 @Sources_v2 = (@Sources_v2, "type_test_member_type type_test_member_type::func1(type_test_member_type param)\n{\n return param;\n}");
4703
4704 #Member_BaseType
4705 @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};");
4706 @Sources_v1 = (@Sources_v1, "type_test_member_basetype type_test_member_basetype::func1(type_test_member_basetype param)\n{\n return param;\n}");
4707
4708 @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};");
4709 @Sources_v2 = (@Sources_v2, "type_test_member_basetype type_test_member_basetype::func1(type_test_member_basetype param)\n{\n return param;\n}");
4710
4711 #Member_PointerLevel_And_Size
4712 @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};");
4713 @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}");
4714
4715 @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};");
4716 @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}");
4717
4718 #Member_PointerLevel
4719 @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};");
4720 @Sources_v1 = (@Sources_v1, "type_test_member_pointerlevel type_test_member_pointerlevel::func1(type_test_member_pointerlevel param)\n{\n return param;\n}");
4721
4722 @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};");
4723 @Sources_v2 = (@Sources_v2, "type_test_member_pointerlevel type_test_member_pointerlevel::func1(type_test_member_pointerlevel param)\n{\n return param;\n}");
4724
4725 #Added_Interface (function)
4726 @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};");
4727 @Sources_v1 = (@Sources_v1, "type_test_added_interface type_test_added_interface::func1(type_test_added_interface param)\n{\n return param;\n}");
4728
4729 @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};");
4730 @DataDefs_v2 = (@DataDefs_v2, "int added_func_2(void *** param);");
4731 @Sources_v2 = (@Sources_v2, "type_test_added_interface type_test_added_interface::func1(type_test_added_interface param)\n{\n return param;\n}");
4732 @Sources_v2 = (@Sources_v2, "type_test_added_interface type_test_added_interface::added_func(type_test_added_interface param)\n{\n return param;\n}");
4733 @Sources_v2 = (@Sources_v2, "int added_func_2(void *** param)\n{\n return 0;\n}");
4734
4735 #Added_Interface (global variable)
4736 @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};");
4737 @Sources_v1 = (@Sources_v1, "int type_test_added_variable::func1(type_test_added_variable param)\n{\n return i;\n}");
4738
4739 @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};");
4740 @Sources_v2 = (@Sources_v2, "int type_test_added_variable::func1(type_test_added_variable param)\n{\n return type_test_added_variable::i;\n}");
4741 @Sources_v2 = (@Sources_v2, "int type_test_added_variable::i=0;");
4742
4743 #Withdrawn_Interface
4744 @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};");
4745 @DataDefs_v1 = (@DataDefs_v1, "int withdrawn_func_2(void *** param);");
4746 @Sources_v1 = (@Sources_v1, "type_test_withdrawn_interface type_test_withdrawn_interface::func1(type_test_withdrawn_interface param)\n{\n return param;\n}");
4747 @Sources_v1 = (@Sources_v1, "type_test_withdrawn_interface type_test_withdrawn_interface::withdrawn_func(type_test_withdrawn_interface param)\n{\n return param;\n}");
4748 @Sources_v1 = (@Sources_v1, "int withdrawn_func_2(void *** param)\n{\n return 0;\n}");
4749
4750 @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};");
4751 @Sources_v2 = (@Sources_v2, "type_test_withdrawn_interface type_test_withdrawn_interface::func1(type_test_withdrawn_interface param)\n{\n return param;\n}");
4752
4753 #Function_Become_Static
4754 @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};");
4755 @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}");
4756
4757 @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};");
4758 @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}");
4759
4760 #Function_Become_NonStatic
4761 @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};");
4762 @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}");
4763
4764 @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};");
4765 @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}");
4766
4767 #Parameter_Type_And_Size
4768 @DataDefs_v1 = (@DataDefs_v1, "int func_parameter_type_and_size(int param, int other_param);");
4769 @Sources_v1 = (@Sources_v1, "int func_parameter_type_and_size(int param, int other_param)\n{\n return other_param;\n}");
4770
4771 @DataDefs_v2 = (@DataDefs_v2, "int func_parameter_type_and_size(long long param, int other_param);");
4772 @Sources_v2 = (@Sources_v2, "int func_parameter_type_and_size(long long param, int other_param)\n{\n return other_param;\n}");
4773
4774 #Parameter_Type
4775 @DataDefs_v1 = (@DataDefs_v1, "int func_parameter_type(int param, int other_param);");
4776 @Sources_v1 = (@Sources_v1, "int func_parameter_type(int param, int other_param)\n{\n return other_param;\n}");
4777
4778 @DataDefs_v2 = (@DataDefs_v2, "int func_parameter_type(float param, int other_param);");
4779 @Sources_v2 = (@Sources_v2, "int func_parameter_type(float param, int other_param)\n{\n return other_param;\n}");
4780
4781 #Parameter_BaseType
4782 @DataDefs_v1 = (@DataDefs_v1, "int func_parameter_basetypechange(int *param);");
4783 @Sources_v1 = (@Sources_v1, "int func_parameter_basetypechange(int *param)\n{\n return sizeof(*param);\n}");
4784
4785 @DataDefs_v2 = (@DataDefs_v2, "int func_parameter_basetypechange(long long *param);");
4786 @Sources_v2 = (@Sources_v2, "int func_parameter_basetypechange(long long *param)\n{\n return sizeof(*param);\n}");
4787
4788 #Parameter_PointerLevel_And_Size
4789 @DataDefs_v1 = (@DataDefs_v1, "long long func_parameter_pointerlevel_and_size(long long param);");
4790 @Sources_v1 = (@Sources_v1, "long long func_parameter_pointerlevel_and_size(long long param)\n{\n return param;\n}");
4791
4792 @DataDefs_v2 = (@DataDefs_v2, "long long func_parameter_pointerlevel_and_size(long long *param);");
4793 @Sources_v2 = (@Sources_v2, "long long func_parameter_pointerlevel_and_size(long long *param)\n{\n return param[5];\n}");
4794
4795 #Parameter_PointerLevel
4796 @DataDefs_v1 = (@DataDefs_v1, "int func_parameter_pointerlevel(int *param);");
4797 @Sources_v1 = (@Sources_v1, "int func_parameter_pointerlevel(int *param)\n{\n return param[5];\n}");
4798
4799 @DataDefs_v2 = (@DataDefs_v2, "int func_parameter_pointerlevel(int **param);");
4800 @Sources_v2 = (@Sources_v2, "int func_parameter_pointerlevel(int **param)\n{\n return param[5][5];\n}");
4801
4802 #Return_Type_And_Size
4803 @DataDefs_v1 = (@DataDefs_v1, "int func_return_type_and_size(int param);");
4804 @Sources_v1 = (@Sources_v1, "int func_return_type_and_size(int param)\n{\n return 2^(sizeof(int)*8-1)-1;\n}");
4805
4806 @DataDefs_v2 = (@DataDefs_v2, "long long func_return_type_and_size(int param);");
4807 @Sources_v2 = (@Sources_v2, "long long func_return_type_and_size(int param)\n{\n return 2^(sizeof(long long)*8-1)-1;\n}");
4808
4809 #Return_Type
4810 @DataDefs_v1 = (@DataDefs_v1, "int func_return_type(int param);");
4811 @Sources_v1 = (@Sources_v1, "int func_return_type(int param)\n{\n return 2^(sizeof(int)*8-1)-1;\n}");
4812
4813 @DataDefs_v2 = (@DataDefs_v2, "float func_return_type(int param);");
4814 @Sources_v2 = (@Sources_v2, "float func_return_type(int param)\n{\n return 0.7;\n}");
4815
4816 #Return_BaseType
4817 @DataDefs_v1 = (@DataDefs_v1, "int *func_return_basetype(int param);");
4818 @Sources_v1 = (@Sources_v1, "int *func_return_basetype(int param)\n{\n int *x = new int[10];\n return x;\n}");
4819
4820 @DataDefs_v2 = (@DataDefs_v2, "long long *func_return_basetype(int param);");
4821 @Sources_v2 = (@Sources_v2, "long long *func_return_basetype(int param)\n{\n long long *x = new long long[10];\n return x;\n}");
4822
4823 #Return_PointerLevel_And_Size
4824 @DataDefs_v1 = (@DataDefs_v1, "long long func_return_pointerlevel_and_size(int param);");
4825 @Sources_v1 = (@Sources_v1, "long long func_return_pointerlevel_and_size(int param)\n{\n return 100;\n}");
4826
4827 @DataDefs_v2 = (@DataDefs_v2, "long long *func_return_pointerlevel_and_size(int param);");
4828 @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}");
4829
4830 #Return_PointerLevel
4831 @DataDefs_v1 = (@DataDefs_v1, "int* func_return_pointerlevel(int param);");
4832 @Sources_v1 = (@Sources_v1, "int* func_return_pointerlevel(int param)\n{\n int* x = new int[10];\n return x;\n}");
4833
4834 @DataDefs_v2 = (@DataDefs_v2, "int **func_return_pointerlevel(int param);");
4835 @Sources_v2 = (@Sources_v2, "int **func_return_pointerlevel(int param)\n{\n int** x = new int*[10];\n return x;\n}");
4836
4837 #typedef to anon struct
4838 @DataDefs_v1 = (@DataDefs_v1, "
4839 typedef struct
4840 {
4841 public:
4842 int i;
4843 long j;
4844 double k;
4845 } type_test_anon_typedef;
4846 int func_test_anon_typedef(type_test_anon_typedef param);");
4847 @Sources_v1 = (@Sources_v1, "int func_test_anon_typedef(type_test_anon_typedef param)\n{\n return 0;\n}");
4848
4849 @DataDefs_v2 = (@DataDefs_v2, "
4850 typedef struct
4851 {
4852 public:
4853 int i;
4854 long j;
4855 double k;
4856 union {
4857 int dummy[256];
4858 struct {
4859 char q_skiptable[256];
4860 const char *p;
4861 int l;
4862 } p;
4863 };
4864 } type_test_anon_typedef;
4865 int func_test_anon_typedef(type_test_anon_typedef param);");
4866 @Sources_v2 = (@Sources_v2, "int func_test_anon_typedef(type_test_anon_typedef param)\n{\n return 0;\n}");
4867
4868 #opaque type
4869 @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};");
4870 @Sources_v1 = (@Sources_v1, "type_test_opaque type_test_opaque::func1(type_test_opaque param)\n{\n return param;\n}");
4871
4872 @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};");
4873 @Sources_v2 = (@Sources_v2, "type_test_opaque type_test_opaque::func1(type_test_opaque param)\n{\n return param;\n}");
4874
4875 #internal function
4876 @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};");
4877 @Sources_v1 = (@Sources_v1, "type_test_internal type_test_internal::func1(type_test_internal param)\n{\n return param;\n}");
4878
4879 @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};");
4880 @Sources_v2 = (@Sources_v2, "type_test_internal type_test_internal::func1(type_test_internal param)\n{\n return param;\n}");
4881
4882 #starting versioning
4883 @DataDefs_v1 = (@DataDefs_v1, "int func_return_type_and_start_versioning(int param);");
4884 @Sources_v1 = (@Sources_v1, "int func_return_type_and_start_versioning(int param)\n{\n return 2^(sizeof(int)*8-1)-1;\n}");
4885
4886 @DataDefs_v2 = (@DataDefs_v2, "int func_return_type_and_start_versioning(int param);");
4887 @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\");");
4888
4889 #Return_Type And Good Versioning
4890 @DataDefs_v1 = (@DataDefs_v1, "int func_return_type_and_good_versioning(int param);");
4891 @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\");");
4892
4893 @DataDefs_v2 = (@DataDefs_v2, "int func_return_type_and_good_versioning_old(int param);");
4894 @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\");");
4895
4896 @DataDefs_v2 = (@DataDefs_v2, "float func_return_type_and_good_versioning(int param);");
4897 @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\");");
4898
4899 #Return_Type and bad versioning
4900 @DataDefs_v1 = (@DataDefs_v1, "int func_return_type_and_bad_versioning(int param);");
4901 @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\");");
4902
4903 @DataDefs_v2 = (@DataDefs_v2, "float func_return_type_and_bad_versioning_old(int param);");
4904 @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\");");
4905
4906 @DataDefs_v2 = (@DataDefs_v2, "float func_return_type_and_bad_versioning(int param);");
4907 @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\");");
4908
4909 #unnamed struct fields within structs
4910 @DataDefs_v1 = (@DataDefs_v1, "
4911 typedef struct {
4912 int a;
4913 struct {
4914 int b;
4915 float c;
4916 };
4917 int d;
4918 } type_test_unnamed;
4919 int func_test_unnamed(type_test_unnamed param);");
4920 @Sources_v1 = (@Sources_v1, "int func_test_unnamed(type_test_unnamed param)\n{\n return 0;\n}");
4921
4922 @DataDefs_v2 = (@DataDefs_v2, "
4923 typedef struct {
4924 int a;
4925 struct {
4926 long double b;
4927 float c;
4928 };
4929 int d;
4930 } type_test_unnamed;
4931 int func_test_unnamed(type_test_unnamed param);");
4932 @Sources_v2 = (@Sources_v2, "int func_test_unnamed(type_test_unnamed param)\n{\n return 0;\n}");
4933
4934 #constants
4935 @DataDefs_v1 = (@DataDefs_v1, "#define TEST_PUBLIC_CONSTANT \"old_value\"");
4936 @DataDefs_v2 = (@DataDefs_v2, "#define TEST_PUBLIC_CONSTANT \"new_value\"");
4937
4938 @DataDefs_v1 = (@DataDefs_v1, "#define TEST_PRIVATE_CONSTANT \"old_value\"\n#undef TEST_PRIVATE_CONSTANT");
4939 @DataDefs_v2 = (@DataDefs_v2, "#define TEST_PRIVATE_CONSTANT \"new_value\"\n#undef TEST_PRIVATE_CONSTANT");
4940
4941 #unions
4942 @DataDefs_v1 = (@DataDefs_v1, "
4943 union type_test_union {
4944 int a;
4945 struct {
4946 int b;
4947 float c;
4948 };
4949 int d;
4950 };
4951 int func_test_union(type_test_union param);");
4952 @Sources_v1 = (@Sources_v1, "int func_test_union(type_test_union param)\n{\n return 0;\n}");
4953
4954 @DataDefs_v2 = (@DataDefs_v2, "
4955 union type_test_union {
4956 int a;
4957 long double new_member;
4958 struct {
4959 int b;
4960 float c;
4961 };
4962 int d;
4963 };
4964 int func_test_union(type_test_union param);");
4965 @Sources_v2 = (@Sources_v2, "int func_test_union(type_test_union param)\n{\n return 0;\n}");
4966
4967 #typedefs
4968 @DataDefs_v1 = (@DataDefs_v1, "typedef float TYPEDEF_TYPE;\nint func_parameter_typedef_change(TYPEDEF_TYPE param);");
4969 @Sources_v1 = (@Sources_v1, "int func_parameter_typedef_change(TYPEDEF_TYPE param)\n{\n return 1;\n}");
4970
4971 @DataDefs_v2 = (@DataDefs_v2, "typedef int TYPEDEF_TYPE;\nint func_parameter_typedef_change(TYPEDEF_TYPE param);");
4972 @Sources_v2 = (@Sources_v2, "int func_parameter_typedef_change(TYPEDEF_TYPE param)\n{\n return 1;\n}");
4973
4974 #typedefs in member type
4975 @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);");
4976 @Sources_v1 = (@Sources_v1, "int func_test_member_typedef_change(type_test_member_typedef_change param)\n{\n return 1;\n}");
4977
4978 @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);");
4979 @Sources_v2 = (@Sources_v2, "int func_test_member_typedef_change(type_test_member_typedef_change param)\n{\n return 1;\n}");
4980
4981 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_");
4982 }
4983
4984 sub testSystem_c()
4985 {
4986 print "\ntesting for C library changes\n";
4987 my (@DataDefs_v1, @Sources_v1, @DataDefs_v2, @Sources_v2) = ();
4988
4989 #Withdrawn_Parameter
4990 @DataDefs_v1 = (@DataDefs_v1, "int func_withdrawn_parameter(int param, int withdrawn_param);");
4991 @Sources_v1 = (@Sources_v1, "int func_withdrawn_parameter(int param, int withdrawn_param)\n{\n return 0;\n}");
4992
4993 @DataDefs_v2 = (@DataDefs_v2, "int func_withdrawn_parameter(int param);");
4994 @Sources_v2 = (@Sources_v2, "int func_withdrawn_parameter(int param)\n{\n return 0;\n}");
4995
4996 #Added_Parameter
4997 @DataDefs_v1 = (@DataDefs_v1, "int func_added_parameter(int param);");
4998 @Sources_v1 = (@Sources_v1, "int func_added_parameter(int param)\n{\n return 0;\n}");
4999
5000 @DataDefs_v2 = (@DataDefs_v2, "int func_added_parameter(int param, int added_param);");
5001 @Sources_v2 = (@Sources_v2, "int func_added_parameter(int param, int added_param)\n{\n return 0;\n}");
5002
5003 #added function with typedef funcptr parameter
5004 @DataDefs_v2 = (@DataDefs_v2, "typedef int (*FUNCPTR_TYPE)(int a, int b);\nint added_function_param_typedef_funcptr(FUNCPTR_TYPE*const** f);");
5005 @Sources_v2 = (@Sources_v2, "int added_function_param_typedef_funcptr(FUNCPTR_TYPE*const** f)\n{\n return 0;\n}");
5006
5007 #added function with funcptr parameter
5008 @DataDefs_v2 = (@DataDefs_v2, "int added_function_param_funcptr(int(*func)(int, int));");
5009 @Sources_v2 = (@Sources_v2, "int added_function_param_funcptr(int(*func)(int, int))\n{\n return 0;\n}");
5010
5011 #added function with no limited parameters
5012 @DataDefs_v2 = (@DataDefs_v2, "int added_function_nolimit_param(float p1, ...);");
5013 @Sources_v2 = (@Sources_v2, "int added_function_nolimit_param(float p1, ...)\n{\n return 0;\n}");
5014
5015 #size change
5016 @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};");
5017 @DataDefs_v1 = (@DataDefs_v1, "int func_test_type_size(struct type_test_size param, int param_2);");
5018 @Sources_v1 = (@Sources_v1, "int func_test_type_size(struct type_test_size param, int param_2)\n{\n return param_2;\n}");
5019
5020 @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};");
5021 @DataDefs_v2 = (@DataDefs_v2, "int func_test_type_size(struct type_test_size param, int param_2);");
5022 @Sources_v2 = (@Sources_v2, "int func_test_type_size(struct type_test_size param, int param_2)\n{\n return param_2;\n}");
5023
5024 #Added_Member_And_Size
5025 @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};");
5026 @DataDefs_v1 = (@DataDefs_v1, "int func_test_added_member(struct type_test_added_member param, int param_2);");
5027 @Sources_v1 = (@Sources_v1, "int func_test_added_member(struct type_test_added_member param, int param_2)\n{\n return param_2;\n}");
5028
5029 @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};");
5030 @DataDefs_v2 = (@DataDefs_v2, "int func_test_added_member(struct type_test_added_member param, int param_2);");
5031 @Sources_v2 = (@Sources_v2, "int func_test_added_member(struct type_test_added_member param, int param_2)\n{\n return param_2;\n}");
5032
5033 #Added_Middle_Member_And_Size
5034 @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};");
5035 @DataDefs_v1 = (@DataDefs_v1, "int func_test_added_middle_member(struct type_test_added_middle_member param, int param_2);");
5036 @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}");
5037
5038 @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};");
5039 @DataDefs_v2 = (@DataDefs_v2, "int func_test_added_middle_member(struct type_test_added_middle_member param, int param_2);");
5040 @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}");
5041
5042 #Member_Rename
5043 @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};");
5044 @DataDefs_v1 = (@DataDefs_v1, "int func_test_member_rename(struct type_test_member_rename param, int param_2);");
5045 @Sources_v1 = (@Sources_v1, "int func_test_member_rename(struct type_test_member_rename param, int param_2)\n{\n return param_2;\n}");
5046
5047 @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};");
5048 @DataDefs_v2 = (@DataDefs_v2, "int func_test_member_rename(struct type_test_member_rename param, int param_2);");
5049 @Sources_v2 = (@Sources_v2, "int func_test_member_rename(struct type_test_member_rename param, int param_2)\n{\n return param_2;\n}");
5050
5051 #Withdrawn_Member_And_Size
5052 @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};");
5053 @DataDefs_v1 = (@DataDefs_v1, "int func_test_withdrawn_member(struct type_test_withdrawn_member param, int param_2);");
5054 @Sources_v1 = (@Sources_v1, "int func_test_withdrawn_member(struct type_test_withdrawn_member param, int param_2)\n{\n return param_2;\n}");
5055
5056 @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};");
5057 @DataDefs_v2 = (@DataDefs_v2, "int func_test_withdrawn_member(struct type_test_withdrawn_member param, int param_2);");
5058 @Sources_v2 = (@Sources_v2, "int func_test_withdrawn_member(struct type_test_withdrawn_member param, int param_2)\n{\n return param_2;\n}");
5059
5060 #Withdrawn_Middle_Member
5061 @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};");
5062 @DataDefs_v1 = (@DataDefs_v1, "int func_test_withdrawn_middle_member(struct type_test_withdrawn_middle_member param, int param_2);");
5063 @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}");
5064
5065 @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};");
5066 @DataDefs_v2 = (@DataDefs_v2, "int func_test_withdrawn_middle_member(struct type_test_withdrawn_middle_member param, int param_2);");
5067 @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}");
5068
5069 #Enum_Member_Value
5070 @DataDefs_v1 = (@DataDefs_v1, "enum type_test_enum_member_value_change\n{\n MEMBER_1=1,\n MEMBER_2=2\n};");
5071 @DataDefs_v1 = (@DataDefs_v1, "int func_test_enum_member_value_change(enum type_test_enum_member_value_change param);");
5072 @Sources_v1 = (@Sources_v1,
5073 "int func_test_enum_member_value_change(enum type_test_enum_member_value_change param)
5074 {
5075 switch(param)
5076 {
5077 case 1:
5078 return 1;
5079 case 2:
5080 return 2;
5081 }
5082 return 0;
5083 }");
5084
5085 @DataDefs_v2 = (@DataDefs_v2, "enum type_test_enum_member_value_change\n{\n MEMBER_1=2,\n MEMBER_2=1\n};");
5086 @DataDefs_v2 = (@DataDefs_v2, "int func_test_enum_member_value_change(enum type_test_enum_member_value_change param);");
5087 @Sources_v2 = (@Sources_v2,
5088 "int func_test_enum_member_value_change(enum type_test_enum_member_value_change param)
5089 {
5090 switch(param)
5091 {
5092 case 1:
5093 return 1;
5094 case 2:
5095 return 2;
5096 }
5097 return 0;
5098 }");
5099
5100 #Enum_Member_Name
5101 @DataDefs_v1 = (@DataDefs_v1, "enum type_test_enum_member_rename\n{\n BRANCH_1=1,\n BRANCH_2=2\n};");
5102 @DataDefs_v1 = (@DataDefs_v1, "int func_test_enum_member_rename(enum type_test_enum_member_rename param);");
5103 @Sources_v1 = (@Sources_v1,
5104 "int func_test_enum_member_rename(enum type_test_enum_member_rename param)
5105 {
5106 switch(param)
5107 {
5108 case 1:
5109 return 1;
5110 case 2:
5111 return 2;
5112 }
5113 return 0;
5114 }");
5115
5116 @DataDefs_v2 = (@DataDefs_v2, "enum type_test_enum_member_rename\n{\n BRANCH_FIRST=1,\n BRANCH_SECOND=1\n};");
5117 @DataDefs_v2 = (@DataDefs_v2, "int func_test_enum_member_rename(enum type_test_enum_member_rename param);");
5118 @Sources_v2 = (@Sources_v2,
5119 "int func_test_enum_member_rename(enum type_test_enum_member_rename param)
5120 {
5121 switch(param)
5122 {
5123 case 1:
5124 return 1;
5125 case 2:
5126 return 2;
5127 }
5128 return 0;
5129 }");
5130
5131 #Member_Type_And_Size
5132 @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};");
5133 @DataDefs_v1 = (@DataDefs_v1, "int func_test_member_type_and_size(struct type_test_member_type_and_size param, int param_2);");
5134 @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}");
5135
5136 @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};");
5137 @DataDefs_v2 = (@DataDefs_v2, "int func_test_member_type_and_size(struct type_test_member_type_and_size param, int param_2);");
5138 @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}");
5139
5140 #Member_Type
5141 @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};");
5142 @DataDefs_v1 = (@DataDefs_v1, "int func_test_member_type(struct type_test_member_type param, int param_2);");
5143 @Sources_v1 = (@Sources_v1, "int func_test_member_type(struct type_test_member_type param, int param_2)\n{\n return param_2;\n}");
5144
5145 @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};");
5146 @DataDefs_v2 = (@DataDefs_v2, "int func_test_member_type(struct type_test_member_type param, int param_2);");
5147 @Sources_v2 = (@Sources_v2, "int func_test_member_type(struct type_test_member_type param, int param_2)\n{\n return param_2;\n}");
5148
5149 #Member_BaseType
5150 @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};");
5151 @DataDefs_v1 = (@DataDefs_v1, "int func_test_member_basetype(struct type_test_member_basetype param, int param_2);");
5152 @Sources_v1 = (@Sources_v1, "int func_test_member_basetype(struct type_test_member_basetype param, int param_2)\n{\n return param_2;\n}");
5153
5154 @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};");
5155 @DataDefs_v2 = (@DataDefs_v2, "int func_test_member_basetype(struct type_test_member_basetype param, int param_2);");
5156 @Sources_v2 = (@Sources_v2, "int func_test_member_basetype(struct type_test_member_basetype param, int param_2)\n{\n return param_2;\n}");
5157
5158 #Member_PointerLevel_And_Size
5159 @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};");
5160 @DataDefs_v1 = (@DataDefs_v1, "int func_test_member_pointerlevel_and_size(struct type_test_member_pointerlevel_and_size param, int param_2);");
5161 @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}");
5162
5163 @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};");
5164 @DataDefs_v2 = (@DataDefs_v2, "int func_test_member_pointerlevel_and_size(struct type_test_member_pointerlevel_and_size param, int param_2);");
5165 @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}");
5166
5167 #Member_PointerLevel
5168 @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};");
5169 @DataDefs_v1 = (@DataDefs_v1, "int func_test_member_pointerlevel(struct type_test_member_pointerlevel param, int param_2);");
5170 @Sources_v1 = (@Sources_v1, "int func_test_member_pointerlevel(struct type_test_member_pointerlevel param, int param_2)\n{\n return param_2;\n}");
5171
5172 @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};");
5173 @DataDefs_v2 = (@DataDefs_v2, "int func_test_member_pointerlevel(struct type_test_member_pointerlevel param, int param_2);");
5174 @Sources_v2 = (@Sources_v2, "int func_test_member_pointerlevel(struct type_test_member_pointerlevel param, int param_2)\n{\n return param_2;\n}");
5175
5176 #Added_Interface
5177 @DataDefs_v2 = (@DataDefs_v2, "int added_func(int param);");
5178 @Sources_v2 = (@Sources_v2, "int added_func(int param)\n{\n return param;\n}");
5179
5180 #Withdrawn_Interface
5181 @DataDefs_v1 = (@DataDefs_v1, "int withdrawn_func(int param);");
5182 @Sources_v1 = (@Sources_v1, "int withdrawn_func(int param)\n{\n return param;\n}");
5183
5184 #Parameter_Type_And_Size
5185 @DataDefs_v1 = (@DataDefs_v1, "int func_parameter_type_and_size(int param, int other_param);");
5186 @Sources_v1 = (@Sources_v1, "int func_parameter_type_and_size(int param, int other_param)\n{\n return other_param;\n}");
5187
5188 @DataDefs_v2 = (@DataDefs_v2, "int func_parameter_type_and_size(long long param, int other_param);");
5189 @Sources_v2 = (@Sources_v2, "int func_parameter_type_and_size(long long param, int other_param)\n{\n return other_param;\n}");
5190
5191 #Parameter_Type
5192 @DataDefs_v1 = (@DataDefs_v1, "int func_parameter_type(int param, int other_param);");
5193 @Sources_v1 = (@Sources_v1, "int func_parameter_type(int param, int other_param)\n{\n return other_param;\n}");
5194
5195 @DataDefs_v2 = (@DataDefs_v2, "int func_parameter_type(float param, int other_param);");
5196 @Sources_v2 = (@Sources_v2, "int func_parameter_type(float param, int other_param)\n{\n return other_param;\n}");
5197
5198 #Parameter_BaseType (Typedef)
5199 @DataDefs_v1 = (@DataDefs_v1, "typedef int* PARAM_TYPEDEF;\nint func_parameter_basetypechange_typedef(PARAM_TYPEDEF param);");
5200 @Sources_v1 = (@Sources_v1, "int func_parameter_basetypechange_typedef(PARAM_TYPEDEF param)\n{\n return 0;\n}");
5201
5202 @DataDefs_v2 = (@DataDefs_v2, "typedef const int* PARAM_TYPEDEF;\nint func_parameter_basetypechange_typedef(PARAM_TYPEDEF param);");
5203 @Sources_v2 = (@Sources_v2, "int func_parameter_basetypechange_typedef(PARAM_TYPEDEF param)\n{\n return 0;\n}");
5204
5205 #Parameter_BaseType
5206 @DataDefs_v1 = (@DataDefs_v1, "int func_parameter_basetypechange(int *param);");
5207 @Sources_v1 = (@Sources_v1, "int func_parameter_basetypechange(int *param)\n{\n return sizeof(*param);\n}");
5208
5209 @DataDefs_v2 = (@DataDefs_v2, "int func_parameter_basetypechange(long long *param);");
5210 @Sources_v2 = (@Sources_v2, "int func_parameter_basetypechange(long long *param)\n{\n return sizeof(*param);\n}");
5211
5212 #Parameter_PointerLevel_And_Size
5213 @DataDefs_v1 = (@DataDefs_v1, "long long func_parameter_pointerlevel_and_size(long long param);");
5214 @Sources_v1 = (@Sources_v1, "long long func_parameter_pointerlevel_and_size(long long param)\n{\n return param;\n}");
5215
5216 @DataDefs_v2 = (@DataDefs_v2, "long long func_parameter_pointerlevel_and_size(long long *param);");
5217 @Sources_v2 = (@Sources_v2, "long long func_parameter_pointerlevel_and_size(long long *param)\n{\n return param[5];\n}");
5218
5219 #Parameter_PointerLevel
5220 @DataDefs_v1 = (@DataDefs_v1, "int func_parameter_pointerlevel(int *param);");
5221 @Sources_v1 = (@Sources_v1, "int func_parameter_pointerlevel(int *param)\n{\n return param[5];\n}");
5222
5223 @DataDefs_v2 = (@DataDefs_v2, "int func_parameter_pointerlevel(int **param);");
5224 @Sources_v2 = (@Sources_v2, "int func_parameter_pointerlevel(int **param)\n{\n return param[5][5];\n}");
5225
5226 #Return_Type_And_Size
5227 @DataDefs_v1 = (@DataDefs_v1, "int func_return_type_and_size(int param);");
5228 @Sources_v1 = (@Sources_v1, "int func_return_type_and_size(int param)\n{\n return 2^(sizeof(int)*8-1)-1;\n}");
5229
5230 @DataDefs_v2 = (@DataDefs_v2, "long long func_return_type_and_size(int param);");
5231 @Sources_v2 = (@Sources_v2, "long long func_return_type_and_size(int param)\n{\n return 2^(sizeof(long long)*8-1)-1;\n}");
5232
5233 #Return_Type
5234 @DataDefs_v1 = (@DataDefs_v1, "int func_return_type(int param);");
5235 @Sources_v1 = (@Sources_v1, "int func_return_type(int param)\n{\n return 2^(sizeof(int)*8-1)-1;\n}");
5236
5237 @DataDefs_v2 = (@DataDefs_v2, "float func_return_type(int param);");
5238 @Sources_v2 = (@Sources_v2, "float func_return_type(int param)\n{\n return 0.7;\n}");
5239
5240 #Return_BaseType
5241 @DataDefs_v1 = (@DataDefs_v1, "int *func_return_basetypechange(int param);");
5242 @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}");
5243
5244 @DataDefs_v2 = (@DataDefs_v2, "long long *func_return_basetypechange(int param);");
5245 @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}");
5246
5247 #Return_PointerLevel_And_Size
5248 @DataDefs_v1 = (@DataDefs_v1, "long long func_return_pointerlevel_and_size(int param);");
5249 @Sources_v1 = (@Sources_v1, "long long func_return_pointerlevel_and_size(int param)\n{\n return 100;\n}");
5250
5251 @DataDefs_v2 = (@DataDefs_v2, "long long *func_return_pointerlevel_and_size(int param);");
5252 @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}");
5253
5254 #Return_PointerLevel
5255 @DataDefs_v1 = (@DataDefs_v1, "long long *func_return_pointerlevel(int param);");
5256 @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}");
5257
5258 @DataDefs_v2 = (@DataDefs_v2, "long long **func_return_pointerlevel(int param);");
5259 @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}");
5260
5261 #typedef to anon struct
5262 @DataDefs_v1 = (@DataDefs_v1, "
5263 typedef struct
5264 {
5265 int i;
5266 long j;
5267 double k;
5268 } type_test_anon_typedef;
5269 int func_test_anon_typedef(type_test_anon_typedef param);");
5270 @Sources_v1 = (@Sources_v1, "int func_test_anon_typedef(type_test_anon_typedef param)\n{\n return 0;\n}");
5271
5272 @DataDefs_v2 = (@DataDefs_v2, "
5273 typedef struct
5274 {
5275 int i;
5276 long j;
5277 double k;
5278 union {
5279 int dummy[256];
5280 struct {
5281 char q_skiptable[256];
5282 const char *p;
5283 int l;
5284 } p;
5285 };
5286 } type_test_anon_typedef;
5287 int func_test_anon_typedef(type_test_anon_typedef param);");
5288 @Sources_v2 = (@Sources_v2, "int func_test_anon_typedef(type_test_anon_typedef param)\n{\n return 0;\n}");
5289
5290 #opaque type
5291 @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};");
5292 @DataDefs_v1 = (@DataDefs_v1, "int func_test_opaque(struct type_test_opaque param, int param_2);");
5293 @Sources_v1 = (@Sources_v1, "int func_test_opaque(struct type_test_opaque param, int param_2)\n{\n return param_2;\n}");
5294
5295 @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};");
5296 @DataDefs_v2 = (@DataDefs_v2, "int func_test_opaque(struct type_test_opaque param, int param_2);");
5297 @Sources_v2 = (@Sources_v2, "int func_test_opaque(struct type_test_opaque param, int param_2)\n{\n return param_2;\n}");
5298
5299 #internal function
5300 @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};");
5301 @DataDefs_v1 = (@DataDefs_v1, "int func_test_internal(struct type_test_internal param, int param_2);");
5302 @Sources_v1 = (@Sources_v1, "int func_test_internal(struct type_test_internal param, int param_2)\n{\n return param_2;\n}");
5303
5304 @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};");
5305 @DataDefs_v2 = (@DataDefs_v2, "int func_test_internal(struct type_test_internal param, int param_2);");
5306 @Sources_v2 = (@Sources_v2, "int func_test_internal(struct type_test_internal param, int param_2)\n{\n return param_2;\n}");
5307
5308 #starting versioning
5309 @DataDefs_v1 = (@DataDefs_v1, "int func_return_type_and_start_versioning(int param);");
5310 @Sources_v1 = (@Sources_v1, "int func_return_type_and_start_versioning(int param)\n{\n return 2^(sizeof(int)*8-1)-1;\n}");
5311
5312 @DataDefs_v2 = (@DataDefs_v2, "int func_return_type_and_start_versioning(int param);");
5313 @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\");");
5314
5315 #Return_Type and good versioning
5316 @DataDefs_v1 = (@DataDefs_v1, "int func_return_type_and_good_versioning(int param);");
5317 @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\");");
5318
5319 @DataDefs_v2 = (@DataDefs_v2, "int func_return_type_and_good_versioning_old(int param);");
5320 @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\");");
5321
5322 @DataDefs_v2 = (@DataDefs_v2, "float func_return_type_and_good_versioning(int param);");
5323 @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\");");
5324
5325 #Return_Type and bad versioning
5326 @DataDefs_v1 = (@DataDefs_v1, "int func_return_type_and_bad_versioning(int param);");
5327 @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\");");
5328
5329 @DataDefs_v2 = (@DataDefs_v2, "float func_return_type_and_bad_versioning_old(int param);");
5330 @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\");");
5331
5332 @DataDefs_v2 = (@DataDefs_v2, "float func_return_type_and_bad_versioning(int param);");
5333 @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\");");
5334
5335 #unnamed struct/union fields within structs/unions
5336 @DataDefs_v1 = (@DataDefs_v1, "
5337 typedef struct {
5338 int a;
5339 union {
5340 int b;
5341 float c;
5342 };
5343 int d;
5344 } type_test_unnamed;
5345 int func_test_unnamed(type_test_unnamed param);");
5346 @Sources_v1 = (@Sources_v1, "int func_test_unnamed(type_test_unnamed param)\n{\n return 0;\n}");
5347
5348 @DataDefs_v2 = (@DataDefs_v2, "
5349 typedef struct {
5350 int a;
5351 union {
5352 long double b;
5353 float c;
5354 };
5355 int d;
5356 } type_test_unnamed;
5357 int func_test_unnamed(type_test_unnamed param);");
5358 @Sources_v2 = (@Sources_v2, "int func_test_unnamed(type_test_unnamed param)\n{\n return 0;\n}");
5359
5360 #constants
5361 @DataDefs_v1 = (@DataDefs_v1, "#define TEST_PUBLIC_CONSTANT \"old_value\"");
5362 @DataDefs_v2 = (@DataDefs_v2, "#define TEST_PUBLIC_CONSTANT \"new_value\"");
5363
5364 @DataDefs_v1 = (@DataDefs_v1, "#define TEST_PRIVATE_CONSTANT \"old_value\"\n#undef TEST_PRIVATE_CONSTANT");
5365 @DataDefs_v2 = (@DataDefs_v2, "#define TEST_PRIVATE_CONSTANT \"new_value\"\n#undef TEST_PRIVATE_CONSTANT");
5366
5367 #anon ptr typedef
5368 @DataDefs_v1 = (@DataDefs_v1, "
5369 #ifdef __cplusplus
5370 extern \"C\" {
5371 #endif
5372 typedef struct {
5373 int a;
5374 } *type_test_anonptr_typedef;
5375 extern __attribute__ ((visibility(\"default\"))) int func_test_anonptr_typedef(type_test_anonptr_typedef param);
5376 #ifdef __cplusplus
5377 }
5378 #endif");
5379 @Sources_v1 = (@Sources_v1, "__attribute__ ((visibility(\"default\"))) int func_test_anonptr_typedef(type_test_anonptr_typedef param)\n{\n return 0;\n}");
5380
5381 @DataDefs_v2 = (@DataDefs_v2, "
5382 #ifdef __cplusplus
5383 extern \"C\" {
5384 #endif
5385 typedef struct {
5386 float a;
5387 } *type_test_anonptr_typedef;
5388 extern __attribute__ ((visibility(\"default\"))) int func_test_anonptr_typedef(type_test_anonptr_typedef param);
5389 #ifdef __cplusplus
5390 }
5391 #endif");
5392 @Sources_v2 = (@Sources_v2, "__attribute__ ((visibility(\"default\"))) int func_test_anonptr_typedef(type_test_anonptr_typedef param)\n{\n return 0;\n}");
5393
5394 #typedefs
5395 @DataDefs_v1 = (@DataDefs_v1, "typedef float TYPEDEF_TYPE;\nint func_parameter_typedef_change(TYPEDEF_TYPE param);");
5396 @Sources_v1 = (@Sources_v1, "int func_parameter_typedef_change(TYPEDEF_TYPE param)\n{\n return 1.0;\n}");
5397
5398 @DataDefs_v2 = (@DataDefs_v2, "typedef int TYPEDEF_TYPE;\nint func_parameter_typedef_change(TYPEDEF_TYPE param);");
5399 @Sources_v2 = (@Sources_v2, "int func_parameter_typedef_change(TYPEDEF_TYPE param)\n{\n return 1;\n}");
5400
5401 #typedefs in member type
5402 @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);");
5403 @Sources_v1 = (@Sources_v1, "int func_test_member_typedef_change(struct type_test_member_typedef_change param)\n{\n return 1;\n}");
5404
5405 @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);");
5406 @Sources_v2 = (@Sources_v2, "int func_test_member_typedef_change(struct type_test_member_typedef_change param)\n{\n return 1;\n}");
5407
5408 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");
5409 }
5410
5411 sub create_TestSuite($$$$$$$$)
5412 {
5413 my ($Dir, $Lang, $DataDefs_v1, $Sources_v1, $DataDefs_v2, $Sources_v2, $Opaque, $Private) = @_;
5414 my $Ext = ($Lang eq "C++")?"cpp":"c";
5415 my $Gcc = ($Lang eq "C++")?"g++":"gcc";
5416 #creating test suite
5417 my $Path_v1 = "$Dir/lib_abi_changes_test.v1";
5418 my $Path_v2 = "$Dir/lib_abi_changes_test.v2";
5419
5420 system("rm", "-fr", $Path_v1, $Path_v2);
5421 system("mkdir", "-p", $Path_v1, $Path_v2);
5422
5423 writeFile("$Path_v1/version", "TEST_1.0 {\n};\nTEST_2.0 {\n};\n");
5424 writeFile("$Path_v1/lib_abi_changes_test.h", "#include <stdlib.h>\n".$DataDefs_v1."\n");
5425 writeFile("$Path_v1/lib_abi_changes_test.$Ext", "#include \"lib_abi_changes_test.h\"\n".$Sources_v1."\n");
5426 writeFile("$Dir/descriptor.v1", "<version>\n 1.0.0\n</version>\n\n<headers>\n ".$ENV{"PWD"}."/$Path_v1/\n</headers>\n\n<libs>\n ".$ENV{"PWD"}."/$Path_v1/\n</libs>\n\n<opaque_types>\n $Opaque\n</opaque_types>\n\n<skip_interfaces>\n $Private\n</skip_interfaces>\n\n<include_paths>\n ".$ENV{"PWD"}."/$Path_v1\n</include_paths>\n");
5427
5428 writeFile("$Path_v2/version", "TEST_1.0 {\n};\nTEST_2.0 {\n};\n");
5429 writeFile("$Path_v2/lib_abi_changes_test.h", "#include <stdlib.h>\n".$DataDefs_v2."\n");
5430 writeFile("$Path_v2/lib_abi_changes_test.$Ext", "#include \"lib_abi_changes_test.h\"\n".$Sources_v2."\n");
5431 writeFile("$Dir/descriptor.v2", "<version>\n 2.0.0\n</version>\n\n<headers>\n ".$ENV{"PWD"}."/$Path_v2/\n</headers>\n\n<libs>\n ".$ENV{"PWD"}."/$Path_v2/\n</libs>\n\n<opaque_types>\n $Opaque\n</opaque_types>\n\n<skip_interfaces>\n $Private\n</skip_interfaces>\n\n<include_paths>\n ".$ENV{"PWD"}."/$Path_v2\n</include_paths>\n");
5432
5433 system("$Gcc $Path_v1/lib_abi_changes_test.h");
5434 if($?)
5435 {
5436 print "ERROR: can't compile \'$Path_v1/lib_abi_changes_test.h\'\n";
5437 return;
5438 }
5439 system("$Gcc -Wl,--version-script $Path_v1/version -shared $Path_v1/lib_abi_changes_test.$Ext -o $Path_v1/lib_abi_changes_test.so");
5440 if($?)
5441 {
5442 print "ERROR: can't compile \'$Path_v1/lib_abi_changes_test.$Ext\'\n";
5443 return;
5444 }
5445 system("$Gcc $Path_v2/lib_abi_changes_test.h");
5446 if($?)
5447 {
5448 print "ERROR: can't compile \'$Path_v2/lib_abi_changes_test.h\'\n";
5449 return;
5450 }
5451 system("$Gcc -Wl,--version-script $Path_v2/version -shared $Path_v2/lib_abi_changes_test.$Ext -o $Path_v2/lib_abi_changes_test.so");
5452 if($?)
5453 {
5454 print "ERROR: can't compile \'$Path_v2/lib_abi_changes_test.$Ext\'\n";
5455 return;
5456 }
5457
5458 #running abi-compliance-checker
5459 system("$0 -l lib_$Dir -d1 $Dir/descriptor.v1 -d2 $Dir/descriptor.v2");
5460 }
5461
5462 sub writeFile($$)
5463 {
5464 my ($Path, $Content) = @_;
5465 return if(not $Path);
5466 open (FILE, ">".$Path) || die ("Can't open file $Path\n");
5467 print FILE $Content;
5468 close(FILE);
5469 }
5470
5471 sub readFile($)
5472 {
5473 my $Path = $_[0];
5474 return "" if(not $Path or not -f $Path);
5475 open (FILE, $Path);
5476 my $Content = join("\n", <FILE>);
5477 close(FILE);
5478 return toUnix($Content);
5479 }
5480
5481 sub toUnix($)
5482 {
5483 my $Text = $_[0];
5484 $Text=~s/\r//g;
5485 return $Text;
5486 }
5487
5488 sub getArch()
5489 {
5490 my $Arch = $ENV{"CPU"};
5491 if(not $Arch)
5492 {
5493 $Arch = `uname -m`;
5494 chomp($Arch);
5495 }
5496 if(not $Arch)
5497 {
5498 $Arch = `uname -p`;
5499 chomp($Arch);
5500 }
5501 $Arch = "x86" if($Arch =~ /i[3-7]86/);
5502 return $Arch;
5503 }
5504
5505 sub get_Report_Header()
5506 {
5507 my $Report_Header = "<h1>ABI compliance report for the library <span style='color:Blue;white-space:nowrap;'>$TargetLibraryName </span> from version <span style='color:Red;white-space:nowrap;'>".$Descriptor{1}{"Version"}."</span> to <span style='color:Red;white-space:nowrap;'>".$Descriptor{2}{"Version"}."</span> on <span style='color:Blue;'>".getArch()."</span> ".(($AppPath)?"relating to the portability of application <span style='color:Blue;'>".get_FileName($AppPath)."</span>":"")."</h1>\n";
5508 return "<!--Header-->\n".$Report_Header."<!--Header_End-->\n";
5509 }
5510
5511 sub get_SourceInfo()
5512 {
5513 my $CheckedHeaders = "<!--Checked_Headers-->\n<a name='Checked_Headers'></a><h2 style='margin-bottom:0px;padding-bottom:0px;'>Checked header files (".keys(%{$Headers{1}}).")</h2><hr/>\n";
5514 foreach my $Header_Dest (sort {lc($Headers{1}{$a}{"Name"}) cmp lc($Headers{1}{$b}{"Name"})} keys(%{$Headers{1}}))
5515 {
5516 my $Header_Name = $Headers{1}{$Header_Dest}{"Name"};
5517 my $Dest_Count = keys(%{$HeaderName_Destinations{1}{$Header_Name}});
5518 my $Identity = $Headers{1}{$Header_Dest}{"Identity"};
5519 my $Dest_Comment = ($Dest_Count>1 and $Identity=~/\//)?" ($Identity)":"";
5520 $CheckedHeaders .= "<span class='header_list_elem'>$Header_Name"."$Dest_Comment</span><br/>\n";
5521 }
5522 $CheckedHeaders .= "<!--Checked_Headers_End--><br/><a style='font-size:11px;' href='#Top'>to the top</a><br/>\n";
5523 my $CheckedLibs = "<!--Checked_Libs-->\n<a name='Checked_Libs'></a><h2 style='margin-bottom:0px;padding-bottom:0px;'>Checked shared objects (".keys(%{$SoNames_All{1}}).")</h2><hr/>\n";
5524 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$SoNames_All{1}}))
5525 {
5526 $CheckedLibs .= "<span class='solib_list_elem'>$Library</span><br/>\n";
5527 }
5528 $CheckedLibs .= "<!--Checked_Libs_End--><br/><a style='font-size:11px;' href='#Top'>to the top</a><br/>\n";
5529 return $CheckedHeaders.$CheckedLibs;
5530 }
5531
5532 sub get_TypeProblems_Count($$)
5533 {
5534 my ($TypeChanges, $TargetPriority) = @_;
5535 my $Type_Problems_Count = 0;
5536 foreach my $TypeName (sort keys(%{$TypeChanges}))
5537 {
5538 my %Kinds_Target = ();
5539 foreach my $Kind (keys(%{$TypeChanges->{$TypeName}}))
5540 {
5541 foreach my $Location (keys(%{$TypeChanges->{$TypeName}{$Kind}}))
5542 {
5543 my $Priority = $TypeChanges->{$TypeName}{$Kind}{$Location}{"Priority"};
5544 next if($Priority ne $TargetPriority);
5545 my $Target = $TypeChanges->{$TypeName}{$Kind}{$Location}{"Target"};
5546 next if($Kinds_Target{$Kind}{$Target});
5547 $Kinds_Target{$Kind}{$Target} = 1;
5548 $Type_Problems_Count += 1;
5549 }
5550 }
5551 }
5552 return $Type_Problems_Count;
5553 }
5554
5555 sub get_Summary()
5556 {
5557 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);
5558 foreach my $Interface (sort keys(%CompatProblems))
5559 {
5560 foreach my $Kind (sort keys(%{$CompatProblems{$Interface}}))
5561 {
5562 if($InterfaceProblems_Kind{$Kind})
5563 {
5564 foreach my $Location (sort keys(%{$CompatProblems{$Interface}{$Kind}}))
5565 {
5566 if($Kind eq "Added_Interface")
5567 {
5568 $Added += 1;
5569 }
5570 elsif($Kind eq "Withdrawn_Interface")
5571 {
5572 $Withdrawn += 1;
5573 }
5574 else
5575 {
5576 if($CompatProblems{$Interface}{$Kind}{$Location}{"Priority"} eq "High")
5577 {
5578 $I_Problems_High += 1;
5579 }
5580 elsif($CompatProblems{$Interface}{$Kind}{$Location}{"Priority"} eq "Medium")
5581 {
5582 $I_Problems_Medium += 1;
5583 }
5584 elsif($CompatProblems{$Interface}{$Kind}{$Location}{"Priority"} eq "Low")
5585 {
5586 $I_Problems_Low += 1;
5587 }
5588 }
5589 }
5590 }
5591 }
5592 }
5593
5594 my (%TypeChanges, %Type_MaxPriority);
5595 foreach my $Interface (sort keys(%CompatProblems))
5596 {
5597 foreach my $Kind (keys(%{$CompatProblems{$Interface}}))
5598 {
5599 if($TypeProblems_Kind{$Kind})
5600 {
5601 foreach my $Location (keys(%{$CompatProblems{$Interface}{$Kind}}))
5602 {
5603 my $Type_Name = $CompatProblems{$Interface}{$Kind}{$Location}{"Type_Name"};
5604 my $Priority = $CompatProblems{$Interface}{$Kind}{$Location}{"Priority"};
5605 %{$TypeChanges{$Type_Name}{$Kind}{$Location}} = %{$CompatProblems{$Interface}{$Kind}{$Location}};
5606 $Type_MaxPriority{$Type_Name}{$Kind} = max_priority($Type_MaxPriority{$Type_Name}{$Kind}, $Priority);
5607 }
5608 }
5609 }
5610 }
5611
5612 foreach my $Type_Name (keys(%TypeChanges))
5613 {
5614 foreach my $Kind (keys(%{$TypeChanges{$Type_Name}}))
5615 {
5616 foreach my $Location (keys(%{$TypeChanges{$Type_Name}{$Kind}}))
5617 {
5618 my $Priority = $TypeChanges{$Type_Name}{$Kind}{$Location}{"Priority"};
5619 if(cmp_priority($Type_MaxPriority{$Type_Name}{$Kind}, $Priority))
5620 {
5621 delete($TypeChanges{$Type_Name}{$Kind}{$Location});
5622 }
5623 }
5624 }
5625 }
5626
5627 $T_Problems_High = get_TypeProblems_Count(\%TypeChanges, "High");
5628 $T_Problems_Medium = get_TypeProblems_Count(\%TypeChanges, "Medium");
5629 $T_Problems_Low = get_TypeProblems_Count(\%TypeChanges, "Low");
5630
5631 #summary
5632 my $Summary = "<h2 style='margin-bottom:0px;padding-bottom:0px;'>Summary</h2><hr/>";
5633 $Summary .= "<table cellpadding='3' border='1' style='border-collapse:collapse;'>";
5634
5635
5636 my $Checked_Headers_Link = "0";
5637 $Checked_Headers_Link = "<a href='#Checked_Headers' style='color:Blue;'>".keys(%{$Headers{1}})."</a>" if(keys(%{$Headers{1}})>0);
5638 $Summary .= "<tr><td class='table_header summary_item'>Total header files checked</td><td class='summary_item_value'>$Checked_Headers_Link</td></tr>";
5639
5640 my $Checked_Libs_Link = "0";
5641 $Checked_Libs_Link = "<a href='#Checked_Libs' style='color:Blue;'>".keys(%{$SoNames_All{1}})."</a>" if(keys(%{$SoNames_All{1}})>0);
5642 $Summary .= "<tr><td class='table_header summary_item'>Total shared objects checked</td><td class='summary_item_value'>$Checked_Libs_Link</td></tr>";
5643 $Summary .= "<tr><td class='table_header summary_item'>Total interfaces / types checked</td><td class='summary_item_value'>".keys(%CheckedInterfaces)." / ".keys(%CheckedTypes)."</td></tr>";
5644
5645 my $Verdict = "<span style='color:Green;'><b>Compatible</b></span>";
5646 $Verdict = "<span style='color:Red;'><b>Incompatible</b></span>" if(($Withdrawn>0) or ($I_Problems_High>0) or ($T_Problems_High>0));
5647 $Summary .= "<tr><td class='table_header summary_item'>Verdict</td><td class='summary_item_value'>$Verdict</td></tr>";
5648
5649 $Summary .= "</table>\n";
5650
5651 #problem summary
5652 my $Problem_Summary = "<h2 style='margin-bottom:0px;padding-bottom:0px;'>Problem Summary</h2><hr/>";
5653 $Problem_Summary .= "<table cellpadding='3' border='1' style='border-collapse:collapse;'>";
5654
5655 my $Added_Link = "0";
5656 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>" if($Added>0);
5657 $Problem_Summary .= "<tr><td class='table_header summary_item' colspan='2'>Added interfaces</td><td class='summary_item_value'>$Added_Link</td></tr>";
5658
5659 my $WIthdrawn_Link = "0";
5660 $WIthdrawn_Link = "<a href='#Withdrawn' style='color:Blue;'>$Withdrawn</a>" if($Withdrawn>0);
5661 $Problem_Summary .= "<tr><td class='table_header summary_item' colspan='2'>Withdrawn interfaces</td><td class='summary_item_value'>$WIthdrawn_Link</td></tr>";
5662
5663 my $TH_Link = "0";
5664 $TH_Link = "<a href='#Type_Problems_High' style='color:Blue;'>$T_Problems_High</a>" if($T_Problems_High>0);
5665 $Problem_Summary .= "<tr><td class='table_header summary_item' rowspan='3'>Problems in<br/>Data Types</td><td class='table_header summary_item' style='color:Red;'>High risk</td><td align='right' class='summary_item_value'>$TH_Link</td></tr>";
5666
5667 my $TM_Link = "0";
5668 $TM_Link = "<a href='#Type_Problems_Medium' style='color:Blue;'>$T_Problems_Medium</a>" if($T_Problems_Medium>0);
5669 $Problem_Summary .= "<tr><td class='table_header summary_item'>Medium risk</td><td class='summary_item_value'>$TM_Link</td></tr>";
5670
5671 my $TL_Link = "0";
5672 $TL_Link = "<a href='#Type_Problems_Low' style='color:Blue;'>$T_Problems_Low</a>" if($T_Problems_Low>0);
5673 $Problem_Summary .= "<tr><td class='table_header summary_item'>Low risk</td><td class='summary_item_value'>$TL_Link</td></tr>";
5674
5675 my $IH_Link = "0";
5676 $IH_Link = "<a href='#Interface_Problems_High' style='color:Blue;'>$I_Problems_High</a>" if($I_Problems_High>0);
5677 $Problem_Summary .= "<tr><td class='table_header summary_item' rowspan='3'>Interface<br/>problems</td><td class='table_header summary_item' style='color:Red;'>High risk</td><td class='summary_item_value'>$IH_Link</td></tr>";
5678
5679 my $IM_Link = "0";
5680 $IM_Link = "<a href='#Interface_Problems_Medium' style='color:Blue;'>$I_Problems_Medium</a>" if($I_Problems_Medium>0);
5681 $Problem_Summary .= "<tr><td class='table_header summary_item'>Medium risk</td><td class='summary_item_value'>$IM_Link</td></tr>";
5682
5683 my $IL_Link = "0";
5684 $IL_Link = "<a href='#Interface_Problems_Low' style='color:Blue;'>$I_Problems_Low</a>" if($I_Problems_Low>0);
5685 $Problem_Summary .= "<tr><td class='table_header summary_item'>Low risk</td><td class='summary_item_value'>$IL_Link</td></tr>";
5686
5687 my $ChangedConstants_Link = "0";
5688 $ChangedConstants_Link = "<a href='#Constants' style='color:Blue;'>".keys(%ConstantProblems)."</a>" if(keys(%ConstantProblems)>0);
5689 $Problem_Summary .= "<tr><td class='table_header summary_item' colspan='2'>Constants Problems</td><td class='summary_item_value'>$ChangedConstants_Link</td></tr>";
5690
5691 $Problem_Summary .= "</table>\n";
5692 return "<!--Summary-->\n".$Summary.$Problem_Summary."<!--Summary_End-->\n";
5693 }
5694
5695 sub get_Report_ChangedConstants()
5696 {
5697 my ($CHANGED_CONSTANTS, %HeaderConstant);
5698 foreach my $Name (keys(%ConstantProblems))
5699 {
5700 $HeaderConstant{$ConstantProblems{$Name}{"Header"}}{$Name} = 1;
5701 }
5702 my $Constants_Number = 0;
5703 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%HeaderConstant))
5704 {
5705 $CHANGED_CONSTANTS .= "<span class='header_name'>$HeaderName</span><br/>\n";
5706 foreach my $Name (sort {lc($a) cmp lc($b)} keys(%{$HeaderConstant{$HeaderName}}))
5707 {
5708 $Constants_Number += 1;
5709 my $Old_Value = htmlSpecChars($ConstantProblems{$Name}{"Old_Value"});
5710 my $New_Value = htmlSpecChars($ConstantProblems{$Name}{"New_Value"});
5711 my $Incompatibility = "The value of constant <b>$Name</b> has been changed from <span style='white-space:nowrap;'><b>$Old_Value</b></span> to <span style='white-space:nowrap;'><b>$New_Value</b></span>.";
5712 my $Effect = "If application uses this constant as a parameter of some interface than its execution may change.";
5713 my $ConstantProblemsReport = "<tr><td align='center' valign='top' class='table_header'><span class='problem_num'>1</span></td><td align='left' valign='top'><span class='problem_body'>".$Incompatibility."</span></td><td align='left' valign='top'><span class='problem_body'>$Effect</span></td></tr>\n";
5714 $CHANGED_CONSTANTS .= $ContentSpanStart."<span class='extension'>[+]</span> ".$Name.$ContentSpanEnd."<br/>\n$ContentDivStart<table width='900px' cellpadding='3' cellspacing='0' class='problems_table'><tr><td align='center' width='2%' class='table_header'><span class='problem_title' style='white-space:nowrap;'></span></td><td width='47%' align='center' class='table_header'><span class='problem_sub_title'>Incompatibility</span></td><td align='center' class='table_header'><span class='problem_sub_title'>Effect</span></td></tr>$ConstantProblemsReport</table><br/>$ContentDivEnd\n";
5715 $CHANGED_CONSTANTS = insertIDs($CHANGED_CONSTANTS);
5716 }
5717 $CHANGED_CONSTANTS .= "<br/>\n";
5718 }
5719 if($CHANGED_CONSTANTS)
5720 {
5721 $CHANGED_CONSTANTS = "<a name='Constants'></a><h2 style='margin-bottom:0px;padding-bottom:0px;'>Constants Problems ($Constants_Number)</h2><hr/>\n"."<!--Changed_Constants-->\n".$CHANGED_CONSTANTS."<!--Changed_Constants_End-->\n"."<input id='Changed_Constants_Count' type='hidden' value=\'$Constants_Number\' /><a style='font-size:11px;' href='#Top'>to the top</a><br/>\n";
5722 }
5723 return $CHANGED_CONSTANTS;
5724 }
5725
5726 sub get_Report_Added()
5727 {
5728 my $ADDED_INTERFACES;
5729 #added interfaces
5730 my %FuncAddedInHeaderLib;
5731 foreach my $Interface (sort keys(%CompatProblems))
5732 {
5733 foreach my $Kind (sort keys(%{$CompatProblems{$Interface}}))
5734 {
5735 foreach my $Location (sort keys(%{$CompatProblems{$Interface}{$Kind}}))
5736 {
5737 if($Kind eq "Added_Interface")
5738 {
5739 $FuncAddedInHeaderLib{$CompatProblems{$Interface}{$Kind}{$Location}{"Header"}}{$CompatProblems{$Interface}{$Kind}{$Location}{"New_SoName"}}{$Interface} = 1;
5740 last;
5741 }
5742 }
5743 }
5744 }
5745 my $Added_Number = 0;
5746 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%FuncAddedInHeaderLib))
5747 {
5748 foreach my $SoName (sort {lc($a) cmp lc($b)} keys(%{$FuncAddedInHeaderLib{$HeaderName}}))
5749 {
5750 if($HeaderName)
5751 {
5752 $ADDED_INTERFACES .= "<span class='header_name'>$HeaderName</span>, <span class='solib_name'>$SoName</span><br/>\n";
5753 }
5754 else
5755 {
5756 $ADDED_INTERFACES .= "<span class='solib_name'>$SoName</span><br/>\n";
5757 }
5758 foreach my $Interface (sort {lc($CompatProblems{$a}{"Added_Interface"}{"SharedLibrary"}{"Signature"}) cmp lc($CompatProblems{$b}{"Added_Interface"}{"SharedLibrary"}{"Signature"})} keys(%{$FuncAddedInHeaderLib{$HeaderName}{$SoName}}))
5759 {
5760 $Added_Number += 1;
5761 my $SubReport = "";
5762 my $Signature = $CompatProblems{$Interface}{"Added_Interface"}{"SharedLibrary"}{"Signature"};
5763 if($Interface =~ /\A_Z/)
5764 {
5765 if($Signature)
5766 {
5767 $SubReport = insertIDs($ContentSpanStart.highLight_Signature_Italic_Color(htmlSpecChars($Signature)).$ContentSpanEnd."<br/>\n".$ContentDivStart."<span class='mangled'>[ symbol: <b>$Interface</b> ]</span><br/><br/>".$ContentDivEnd."\n");
5768 }
5769 else
5770 {
5771 $SubReport = "<span class=\"interface_name\">".$Interface."</span>"."<br/>\n";
5772 }
5773 }
5774 else
5775 {
5776 if($Signature)
5777 {
5778 $SubReport = "<span class=\"interface_name\">".highLight_Signature_Italic_Color($Signature)."</span>"."<br/>\n";
5779 }
5780 else
5781 {
5782 $SubReport = "<span class=\"interface_name\">".$Interface."</span>"."<br/>\n";
5783 }
5784 }
5785 $ADDED_INTERFACES .= $SubReport;
5786 }
5787 $ADDED_INTERFACES .= "<br/>\n";
5788 }
5789 }
5790 if($ADDED_INTERFACES)
5791 {
5792 $ADDED_INTERFACES = "<a name='Added'></a><h2 style='margin-bottom:0px;padding-bottom:0px;'>Added Interfaces ($Added_Number)</h2><hr/>\n"."<!--Added_Interfaces-->\n".$ADDED_INTERFACES."<!--Added_Interfaces_End-->\n"."<input id='Added_Interfaces_Count' type='hidden' value=\'$Added_Number\' /><a style='font-size:11px;' href='#Top'>to the top</a><br/>\n";
5793 }
5794 return $ADDED_INTERFACES;
5795 }
5796
5797 sub get_Report_Withdrawn()
5798 {
5799 my $WITHDRAWN_INTERFACES;
5800 #withdrawn interfaces
5801 my %FuncWithdrawnFromHeaderLib;
5802 foreach my $Interface (sort keys(%CompatProblems))
5803 {
5804 foreach my $Kind (sort keys(%{$CompatProblems{$Interface}}))
5805 {
5806 foreach my $Location (sort keys(%{$CompatProblems{$Interface}{$Kind}}))
5807 {
5808 if($Kind eq "Withdrawn_Interface")
5809 {
5810 $FuncWithdrawnFromHeaderLib{$CompatProblems{$Interface}{$Kind}{$Location}{"Header"}}{$CompatProblems{$Interface}{$Kind}{$Location}{"Old_SoName"}}{$Interface} = 1;
5811 last;
5812 }
5813 }
5814 }
5815 }
5816 my $Withdrawn_Number = 0;
5817 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%FuncWithdrawnFromHeaderLib))
5818 {
5819 foreach my $SoName (sort {lc($a) cmp lc($b)} keys(%{$FuncWithdrawnFromHeaderLib{$HeaderName}}))
5820 {
5821 if($HeaderName)
5822 {
5823 $WITHDRAWN_INTERFACES .= "<span class='header_name'>$HeaderName</span>, <span class='solib_name'>$SoName</span><br/>\n";
5824 }
5825 else
5826 {
5827 $WITHDRAWN_INTERFACES .= "<span class='solib_name'>$SoName</span><br/>\n";
5828 }
5829 foreach my $Interface (sort {lc($CompatProblems{$a}{"Withdrawn_Interface"}{"SharedLibrary"}{"Signature"}) cmp lc($CompatProblems{$b}{"Withdrawn_Interface"}{"SharedLibrary"}{"Signature"})} keys(%{$FuncWithdrawnFromHeaderLib{$HeaderName}{$SoName}}))
5830 {
5831 $Withdrawn_Number += 1;
5832 my $SubReport = "";
5833 my $Signature = $CompatProblems{$Interface}{"Withdrawn_Interface"}{"SharedLibrary"}{"Signature"};
5834 if($Interface =~ /\A_Z/)
5835 {
5836 if($Signature)
5837 {
5838 $SubReport = insertIDs($ContentSpanStart.highLight_Signature_Italic_Color(htmlSpecChars($Signature)).$ContentSpanEnd."<br/>\n".$ContentDivStart."<span class='mangled'>[ symbol: <b>$Interface</b> ]</span><br/><br/>".$ContentDivEnd."\n");
5839 }
5840 else
5841 {
5842 $SubReport = "<span class=\"interface_name\">".$Interface."</span>"."<br/>\n";
5843 }
5844 }
5845 else
5846 {
5847 if($Signature)
5848 {
5849 $SubReport = "<span class=\"interface_name\">".highLight_Signature_Italic_Color($Signature)."</span>"."<br/>\n";
5850 }
5851 else
5852 {
5853 $SubReport = "<span class=\"interface_name\">".$Interface."</span>"."<br/>\n";
5854 }
5855 }
5856 $WITHDRAWN_INTERFACES .= $SubReport;
5857 }
5858 $WITHDRAWN_INTERFACES .= "<br/>\n";
5859 }
5860 }
5861 if($WITHDRAWN_INTERFACES)
5862 {
5863 $WITHDRAWN_INTERFACES = "<a name='Withdrawn'></a><h2 style='margin-bottom:0px;padding-bottom:0px;'>Withdrawn Interfaces ($Withdrawn_Number)</h2><hr/>\n"."<!--Withdrawn_Interfaces-->\n".$WITHDRAWN_INTERFACES."<!--Withdrawn_Interfaces_End-->\n"."<input id='Withdrawn_Interfaces_Count' type='hidden' value=\'$Withdrawn_Number\' /><a style='font-size:11px;' href='#Top'>to the top</a><br/>\n";
5864 }
5865 return $WITHDRAWN_INTERFACES;
5866 }
5867
5868 sub get_Report_InterfaceProblems($)
5869 {
5870 my $TargetPriority = $_[0];
5871 my ($INTERFACE_PROBLEMS, %FuncHeaderLib);
5872 foreach my $Interface (sort keys(%CompatProblems))
5873 {
5874 foreach my $Kind (sort keys(%{$CompatProblems{$Interface}}))
5875 {
5876 if($InterfaceProblems_Kind{$Kind} and ($Kind ne "Added_Interface") and ($Kind ne "Withdrawn_Interface"))
5877 {
5878 foreach my $Location (sort keys(%{$CompatProblems{$Interface}{$Kind}}))
5879 {
5880 my $SoName = $CompatProblems{$Interface}{$Kind}{$Location}{"Old_SoName"};
5881 my $HeaderName = $CompatProblems{$Interface}{$Kind}{$Location}{"Header"};
5882 $FuncHeaderLib{$HeaderName}{$SoName}{$Interface} = 1;
5883 last;
5884 }
5885 }
5886 }
5887 }
5888 my $Problems_Number = 0;
5889 #interface problems
5890 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%FuncHeaderLib))
5891 {
5892 foreach my $SoName (sort {lc($a) cmp lc($b)} keys(%{$FuncHeaderLib{$HeaderName}}))
5893 {
5894 my $HEADER_LIB_REPORT = "";
5895 foreach my $Interface (sort {lc($tr_name{$a}) cmp lc($tr_name{$b})} keys(%{$FuncHeaderLib{$HeaderName}{$SoName}}))
5896 {
5897 my $Signature = "";
5898 my $InterfaceProblemsReport = "";
5899 my $ProblemNum = 1;
5900 foreach my $Kind (keys(%{$CompatProblems{$Interface}}))
5901 {
5902 foreach my $Location (keys(%{$CompatProblems{$Interface}{$Kind}}))
5903 {
5904 my $Incompatibility = "";
5905 my $Effect = "";
5906 my $Old_Value = htmlSpecChars($CompatProblems{$Interface}{$Kind}{$Location}{"Old_Value"});
5907 my $New_Value = htmlSpecChars($CompatProblems{$Interface}{$Kind}{$Location}{"New_Value"});
5908 my $Priority = $CompatProblems{$Interface}{$Kind}{$Location}{"Priority"};
5909 my $Target = $CompatProblems{$Interface}{$Kind}{$Location}{"Target"};
5910 my $Old_Size = $CompatProblems{$Interface}{$Kind}{$Location}{"Old_Size"};
5911 my $New_Size = $CompatProblems{$Interface}{$Kind}{$Location}{"New_Size"};
5912 my $InitialType_Type = $CompatProblems{$Interface}{$Kind}{$Location}{"InitialType_Type"};
5913 my $Parameter_Position = $CompatProblems{$Interface}{$Kind}{$Location}{"Parameter_Position"};
5914 my $Parameter_Position_Str = num_to_str($Parameter_Position + 1);
5915 $Signature = $CompatProblems{$Interface}{$Kind}{$Location}{"Signature"} if(not $Signature);
5916 next if($Priority ne $TargetPriority);
5917 if($Kind eq "Function_Become_Static")
5918 {
5919 $Incompatibility = "Function become <b>static</b>.\n";
5920 $Effect = "Layout of parameter's stack has been changed and therefore parameters in higher positions in the stack may be incorrectly initialized by applications.";
5921 }
5922 elsif($Kind eq "Function_Become_NonStatic")
5923 {
5924 $Incompatibility = "Function become <b>non-static</b>.\n";
5925 $Effect = "Layout of parameter's stack has been changed and therefore parameters in higher positions in the stack may be incorrectly initialized by applications.";
5926 }
5927 elsif($Kind eq "Parameter_Type_And_Size")
5928 {
5929 $Incompatibility = "Type of $Parameter_Position_Str parameter <b>$Target</b> has been changed from <span style='white-space:nowrap;'><b>$Old_Value</b> (<b>$Old_Size</b> bytes)</span> to <span style='white-space:nowrap;'><b>$New_Value</b> (<b>$New_Size</b> bytes)</span>.\n";
5930 $Effect = "Layout of parameter's stack has been changed and therefore parameters in higher positions in the stack may be incorrectly initialized by applications.";
5931 }
5932 elsif($Kind eq "Parameter_Type")
5933 {
5934 $Incompatibility = "Type of $Parameter_Position_Str parameter <b>$Target</b> has been changed from <span style='white-space:nowrap;'><b>$Old_Value</b></span> to <span style='white-space:nowrap;'><b>$New_Value</b></span>.\n";
5935 $Effect = "Replacement of parameter data type may indicate a change in the semantic meaning of this parameter.";
5936 }
5937 elsif($Kind eq "Withdrawn_Parameter")
5938 {
5939 $Incompatibility = "$Parameter_Position_Str parameter <b>$Target</b> has been withdrawn from the interface signature.\n";
5940 $Effect = "This parameter will be ignored by the interface.";
5941 }
5942 elsif($Kind eq "Added_Parameter")
5943 {
5944 $Incompatibility = "$Parameter_Position_Str parameter <b>$Target</b> has been added to the interface signature.\n";
5945 $Effect = "This parameter will not be initialized by applications.";
5946 }
5947 elsif($Kind eq "Parameter_BaseType_And_Size")
5948 {
5949 if($InitialType_Type eq "Pointer")
5950 {
5951 $Incompatibility = "Base type of $Parameter_Position_Str parameter <b>$Target</b> (pointer) has been changed from <span style='white-space:nowrap;'><b>$Old_Value</b> (<b>$Old_Size</b> bytes)</span> to <span style='white-space:nowrap;'><b>$New_Value</b> (<b>$New_Size</b> bytes)</span>.\n";
5952 $Effect = "Memory stored by pointer may be incorrectly initialized by applications.";
5953 }
5954 else
5955 {
5956 $Incompatibility = "Base type of $Parameter_Position_Str parameter <b>$Target</b> has been changed from <span style='white-space:nowrap;'><b>$Old_Value</b> (<b>$Old_Size</b> bytes)</span> to <span style='white-space:nowrap;'><b>$New_Value</b> (<b>$New_Size</b> bytes)</span>.\n";
5957 $Effect = "Layout of parameter's stack has been changed and therefore parameters in higher positions in the stack may be incorrectly initialized by applications.";
5958 }
5959 }
5960 elsif($Kind eq "Parameter_BaseType")
5961 {
5962 if($InitialType_Type eq "Pointer")
5963 {
5964 $Incompatibility = "Base type of $Parameter_Position_Str parameter <b>$Target</b> (pointer) has been changed from <span style='white-space:nowrap;'><b>$Old_Value</b></span> to <span style='white-space:nowrap;'><b>$New_Value</b></span>.\n";
5965 $Effect = "Memory stored by pointer may be incorrectly initialized by applications.";
5966 }
5967 else
5968 {
5969 $Incompatibility = "Base type of $Parameter_Position_Str parameter <b>$Target</b> has been changed from <span style='white-space:nowrap;'><b>$Old_Value</b></span> to <span style='white-space:nowrap;'><b>$New_Value</b></span>.\n";
5970 $Effect = "Replacement of parameter base type may indicate a change in the semantic meaning of this parameter.";
5971 }
5972 }
5973 elsif($Kind eq "Parameter_PointerLevel")
5974 {
5975 $Incompatibility = "Type pointer level of $Parameter_Position_Str parameter <b>$Target</b> has been changed from <b>$Old_Value</b> to <b>$New_Value</b>.\n";
5976 $Effect = "Possible incorrect initialization of $Parameter_Position_Str parameter <b>$Target</b> by applications.";
5977 }
5978 elsif($Kind eq "Return_Type_And_Size")
5979 {
5980 $Incompatibility = "Type of return value has been changed from <span style='white-space:nowrap;'><b>$Old_Value</b> (<b>$Old_Size</b> bytes)</span> to <span style='white-space:nowrap;'><b>$New_Value</b> (<b>$New_Size</b> bytes)</span>.\n";
5981 $Effect = "Applications will get a different return value and execution may change.";
5982 }
5983 elsif($Kind eq "Return_Type")
5984 {
5985 $Incompatibility = "Type of return value has been changed from <span style='white-space:nowrap;'><b>$Old_Value</b></span> to <span style='white-space:nowrap;'><b>$New_Value</b></span>.\n";
5986 $Effect = "Replacement of return type may indicate a change in its semantic meaning.";
5987 }
5988 elsif($Kind eq "Return_BaseType_And_Size")
5989 {
5990 $Incompatibility = "Base type of return value has been changed from <span style='white-space:nowrap;'><b>$Old_Value</b> (<b>$Old_Size</b> bytes)</span> to <span style='white-space:nowrap;'><b>$New_Value</b> (<b>$New_Size</b> bytes)</span>.\n";
5991 $Effect = "Applications will get a different return value and execution may change.";
5992 }
5993 elsif($Kind eq "Return_BaseType")
5994 {
5995 $Incompatibility = "Base type of return value has been changed from <span style='white-space:nowrap;'><b>$Old_Value</b></span> to <span style='white-space:nowrap;'><b>$New_Value</b></span>.\n";
5996 $Effect = "Replacement of return base type may indicate a change in its semantic meaning.";
5997 }
5998 elsif($Kind eq "Return_PointerLevel")
5999 {
6000 $Incompatibility = "Type pointer level of return value has been changed from <b>$Old_Value</b> to <b>$New_Value</b>.\n";
6001 $Effect = "Applications will get a different return value and execution may change.";
6002 }
6003 if($Incompatibility)
6004 {
6005 $InterfaceProblemsReport .= "<tr><td align='center' class='table_header'><span class='problem_num'>$ProblemNum</span></td><td align='left' valign='top'><span class='problem_body'>".$Incompatibility."</span></td><td align='left' valign='top'><span class='problem_body'>".$Effect."</span></td></tr>\n";
6006 $ProblemNum += 1;
6007 $Problems_Number += 1;
6008 }
6009 }
6010 }
6011 $ProblemNum -= 1;
6012 if($InterfaceProblemsReport)
6013 {
6014 if($Interface =~ /\A_Z/)
6015 {
6016 if($Signature)
6017 {
6018 $HEADER_LIB_REPORT .= $ContentSpanStart."<span class='extension'>[+]</span> ".highLight_Signature_Italic_Color(htmlSpecChars($Signature))." ($ProblemNum)".$ContentSpanEnd."<br/>\n$ContentDivStart<span class='mangled'>[ symbol: <b>$Interface</b> ]</span><br/>\n";
6019 }
6020 else
6021 {
6022 $HEADER_LIB_REPORT .= $ContentSpanStart."<span class='extension'>[+]</span> ".$Interface." ($ProblemNum)".$ContentSpanEnd."<br/>\n$ContentDivStart\n";
6023 }
6024 }
6025 else
6026 {
6027 if($Signature)
6028 {
6029 $HEADER_LIB_REPORT .= $ContentSpanStart."<span class='extension'>[+]</span> ".highLight_Signature_Italic_Color(htmlSpecChars($Signature))." ($ProblemNum)".$ContentSpanEnd."<br/>\n$ContentDivStart\n";
6030 }
6031 else
6032 {
6033 $HEADER_LIB_REPORT .= $ContentSpanStart."<span class='extension'>[+]</span> ".$Interface." ($ProblemNum)".$ContentSpanEnd."<br/>\n$ContentDivStart\n";
6034 }
6035 }
6036 $HEADER_LIB_REPORT .= "<table width='900px' cellpadding='3' cellspacing='0' class='problems_table'><tr><td align='center' width='2%' class='table_header'><span class='problem_title' style='white-space:nowrap;'></span></td><td width='47%' align='center' class='table_header'><span class='problem_sub_title'>Incompatibility</span></td><td align='center' class='table_header'><span class='problem_sub_title'>Effect</span></td></tr>$InterfaceProblemsReport</table><br/>$ContentDivEnd\n";
6037 $HEADER_LIB_REPORT = insertIDs($HEADER_LIB_REPORT);
6038 }
6039 }
6040 if($HEADER_LIB_REPORT)
6041 {
6042 $INTERFACE_PROBLEMS .= "<span class='header_name'>$HeaderName</span>, <span class='solib_name'>$SoName</span><br/>\n".$HEADER_LIB_REPORT."<br/>";
6043 }
6044 }
6045 }
6046 if($INTERFACE_PROBLEMS)
6047 {
6048 $INTERFACE_PROBLEMS = "<a name=\'Interface_Problems_$TargetPriority\'></a>\n<h2 style='margin-bottom:0px;padding-bottom:0px;'>Interface problems, $TargetPriority risk ($Problems_Number)</h2><hr/>\n"."<!--Interface_Problems_".$TargetPriority."-->\n".$INTERFACE_PROBLEMS."<!--Interface_Problems_".$TargetPriority."_End-->\n"."<input id=\'Interface_Problems_$TargetPriority"."_Count"."\' type='hidden' value=\'$Problems_Number\' /><a style='font-size:11px;' href='#Top'>to the top</a><br/>\n";
6049 }
6050 return $INTERFACE_PROBLEMS;
6051 }
6052
6053 sub get_Report_TypeProblems($)
6054 {
6055 my $TargetPriority = $_[0];
6056 my ($TYPE_PROBLEMS, %TypeHeader, %TypeChanges, %Type_MaxPriority) = ();
6057 foreach my $Interface (sort keys(%CompatProblems))
6058 {
6059 foreach my $Kind (keys(%{$CompatProblems{$Interface}}))
6060 {
6061 if($TypeProblems_Kind{$Kind})
6062 {
6063 foreach my $Location (keys(%{$CompatProblems{$Interface}{$Kind}}))
6064 {
6065 my $Type_Name = $CompatProblems{$Interface}{$Kind}{$Location}{"Type_Name"};
6066 my $Priority = $CompatProblems{$Interface}{$Kind}{$Location}{"Priority"};
6067 my $Type_Header = $CompatProblems{$Interface}{$Kind}{$Location}{"Header"};
6068 %{$TypeChanges{$Type_Name}{$Kind}{$Location}} = %{$CompatProblems{$Interface}{$Kind}{$Location}};
6069 $TypeHeader{$Type_Header}{$Type_Name} = 1;
6070 $Type_MaxPriority{$Type_Name}{$Kind} = max_priority($Type_MaxPriority{$Type_Name}{$Kind}, $Priority);
6071 }
6072 }
6073 }
6074 }
6075 foreach my $Type_Name (keys(%TypeChanges))
6076 {
6077 foreach my $Kind (keys(%{$TypeChanges{$Type_Name}}))
6078 {
6079 foreach my $Location (keys(%{$TypeChanges{$Type_Name}{$Kind}}))
6080 {
6081 my $Priority = $TypeChanges{$Type_Name}{$Kind}{$Location}{"Priority"};
6082 if(cmp_priority($Type_MaxPriority{$Type_Name}{$Kind}, $Priority))
6083 {
6084 delete($TypeChanges{$Type_Name}{$Kind}{$Location});
6085 }
6086 }
6087 }
6088 }
6089 my $Problems_Number = 0;
6090 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%TypeHeader))
6091 {
6092 my $HEADER_REPORT = "";
6093 foreach my $TypeName (sort {lc($a) cmp lc($b)} keys(%{$TypeHeader{$HeaderName}}))
6094 {
6095 my $ProblemNum = 1;
6096 my $TypeProblemsReport = "";
6097 my %Kinds_Locations = ();
6098 my %Kinds_Target = ();
6099 foreach my $Kind (keys(%{$TypeChanges{$TypeName}}))
6100 {
6101 foreach my $Location (keys(%{$TypeChanges{$TypeName}{$Kind}}))
6102 {
6103 my $Priority = $TypeChanges{$TypeName}{$Kind}{$Location}{"Priority"};
6104 next if($Priority ne $TargetPriority);
6105 $Kinds_Locations{$Kind}{$Location} = 1;
6106 my $Incompatibility = "";
6107 my $Effect = "";
6108 my $Target = $TypeChanges{$TypeName}{$Kind}{$Location}{"Target"};
6109 next if($Kinds_Target{$Kind}{$Target});
6110 $Kinds_Target{$Kind}{$Target} = 1;
6111 my $Old_Value = htmlSpecChars($TypeChanges{$TypeName}{$Kind}{$Location}{"Old_Value"});
6112 my $New_Value = htmlSpecChars($TypeChanges{$TypeName}{$Kind}{$Location}{"New_Value"});
6113 my $Old_Size = $TypeChanges{$TypeName}{$Kind}{$Location}{"Old_Size"};
6114 my $New_Size = $TypeChanges{$TypeName}{$Kind}{$Location}{"New_Size"};
6115 my $Type_Type = $TypeChanges{$TypeName}{$Kind}{$Location}{"Type_Type"};
6116 my $InitialType_Type = $TypeChanges{$TypeName}{$Kind}{$Location}{"InitialType_Type"};
6117
6118 if($Kind eq "Added_Virtual_Function")
6119 {
6120 $Incompatibility = "Virtual method "."<span class='interface_name_black'>".highLight_Signature(htmlSpecChars($Target))."</span>"." has been added to this class and therefore the layout of virtual table has been changed.";
6121 $Effect = "Call of any virtual method in this class or its subclasses will result in crash of application.";
6122 }
6123 elsif($Kind eq "Withdrawn_Virtual_Function")
6124 {
6125 $Incompatibility = "Virtual method "."<span class='interface_name_black'>".highLight_Signature(htmlSpecChars($Target))."</span>"." has been withdrawn from this class and therefore the layout of virtual table has been changed.";
6126 $Effect = "Call of any virtual method in this class or its subclasses will result in crash of application.";
6127 }
6128 elsif($Kind eq "Virtual_Function_Position")
6129 {
6130 $Incompatibility = "The relative position of virtual method "."<span class='interface_name_black'>".highLight_Signature(htmlSpecChars($Target))."</span>"." has been changed from <b>$Old_Value</b> to <b>$New_Value</b> and therefore the layout of virtual table has been changed.";
6131 $Effect = "Call of this virtual method will result in crash of application.";
6132 }
6133 elsif($Kind eq "Virtual_Function_Redefinition")
6134 {
6135 $Incompatibility = "Virtual method "."<span class='interface_name_black'>".highLight_Signature(htmlSpecChars($Old_Value))."</span>"." has been redefined by "."<span class='interface_name_black'>".highLight_Signature(htmlSpecChars($New_Value))."</span>";
6136 $Effect = "Method <span class='interface_name_black'>".highLight_Signature(htmlSpecChars($New_Value))."</span> will be called instead of <span class='interface_name_black'>".highLight_Signature(htmlSpecChars($Old_Value))."</span>";
6137 }
6138 elsif($Kind eq "Virtual_Function_Redefinition_B")
6139 {
6140 $Incompatibility = "Virtual method "."<span class='interface_name_black'>".highLight_Signature(htmlSpecChars($New_Value))."</span>"." has been redefined by "."<span class='interface_name_black'>".highLight_Signature(htmlSpecChars($Old_Value))."</span>";
6141 $Effect = "Method <span class='interface_name_black'>".highLight_Signature(htmlSpecChars($Old_Value))."</span> will be called instead of <span class='interface_name_black'>".highLight_Signature(htmlSpecChars($New_Value))."</span>";
6142 }
6143 elsif($Kind eq "Size")
6144 {
6145 $Incompatibility = "Size of this type has been changed from <b>$Old_Value</b> to <b>$New_Value</b> bytes.";
6146 $Effect = "Change of type size may lead to different effects in different contexts. $ContentSpanStart"."<span style='color:Black'>[+] ...</span>"."$ContentSpanEnd <label id=\"CONTENT_ID\" style=\"display:none;\"> In the context of function parameters, this change affects the parameter's stack layout and may lead to incorrect initialization of parameters in higher positions in the stack. In the context of structure members, this change affects the member's layout and may lead to incorrect attempts to access members in higher positions. Other effects are possible.</label>";
6147 }
6148 elsif($Kind eq "BaseType")
6149 {
6150 $Incompatibility = "Base of this type has been changed from <b>$Old_Value</b> to <b>$New_Value</b>.";
6151 $Effect = "Possible incorrect initialization of interface parameters by applications.";
6152 }
6153 elsif($Kind eq "Added_Member_And_Size")
6154 {
6155 $Incompatibility = "Member <b>$Target</b> has been added to this type.";
6156 $Effect = "The size of the inclusive type has been changed.";
6157 }
6158 elsif($Kind eq "Added_Middle_Member_And_Size")
6159 {
6160 $Incompatibility = "Member <b>$Target</b> has been added between the first member and the last member of this structural type.";
6161 $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.<br/>2) The size of the inclusive type will also be affected.";
6162 }
6163 elsif($Kind eq "Member_Rename")
6164 {
6165 $Incompatibility = "Member <b>$Target</b> has been renamed to <b>$New_Value</b>.";
6166 $Effect = "Renaming of a member in a structural data type may indicate a change in the semantic meaning of the member.";
6167 }
6168 elsif($Kind eq "Withdrawn_Member_And_Size")
6169 {
6170 $Incompatibility = "Member <b>$Target</b> has been withdrawn from this type.";
6171 $Effect = "1) Applications will access incorrect memory when attempting to access this member.<br/>2) The size of the inclusive type will also be affected.";
6172 }
6173 elsif($Kind eq "Withdrawn_Member")
6174 {
6175 $Incompatibility = "Member <b>$Target</b> has been withdrawn from this type.";
6176 $Effect = "Applications will access incorrect memory when attempting to access this member.";
6177 }
6178 elsif($Kind eq "Withdrawn_Middle_Member_And_Size")
6179 {
6180 $Incompatibility = "Member <b>$Target</b> has been withdrawn from this structural type between the first member and the last member.";
6181 $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.<br/>2) Previous accesses of applications to the withdrawn member will be incorrect.";
6182 }
6183 elsif($Kind eq "Withdrawn_Middle_Member")
6184 {
6185 $Incompatibility = "Member <b>$Target</b> has been withdrawn from this structural type between the first member and the last member.";
6186 $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.<br/>2) Applications will access incorrect memory when attempting to access this member.";
6187 }
6188 elsif($Kind eq "Enum_Member_Value")
6189 {
6190 $Incompatibility = "Value of member <b>$Target</b> has been changed from <b>$Old_Value</b> to <b>$New_Value</b>.";
6191 $Effect = "Applications may execute another branch of library code.";
6192 }
6193 elsif($Kind eq "Enum_Member_Name")
6194 {
6195 $Incompatibility = "Name of member with value <b>$Target</b> has been changed from <b>$Old_Value</b> to <b>$New_Value</b>.";
6196 $Effect = "Applications may execute another branch of library code.";
6197 }
6198 elsif($Kind eq "Member_Type_And_Size")
6199 {
6200 $Incompatibility = "Type of member <b>$Target</b> has been changed from <span style='white-space:nowrap;'><b>$Old_Value</b> (<b>$Old_Size</b> bytes)</span> to <span style='white-space:nowrap;'><b>$New_Value</b> (<b>$New_Size</b> bytes)</span>.";
6201 $Effect = "Layout of structure members has been changed and therefore members in higher positions in the structure definition may be incorrectly accessed by applications.";
6202 }
6203 elsif($Kind eq "Member_Type")
6204 {
6205 $Incompatibility = "Type of member <b>$Target</b> has been changed from <span style='white-space:nowrap;'><b>$Old_Value</b></span> to <span style='white-space:nowrap;'><b>$New_Value</b></span>.";
6206 $Effect = "Replacement of the member data type may indicate a change in the semantic meaning of the member.";
6207 }
6208 elsif($Kind eq "Member_BaseType_And_Size")
6209 {
6210 if($InitialType_Type eq "Pointer")
6211 {
6212 $Incompatibility = "Base type of member <b>$Target</b> (pointer) has been changed from <span style='white-space:nowrap;'><b>$Old_Value</b> (<b>$Old_Size</b> bytes)</span> to <span style='white-space:nowrap;'><b>$New_Value</b> (<b>$New_Size</b> bytes)</span>.";
6213 $Effect = "Possible access of applications to incorrect memory via member pointer.";
6214 }
6215 else
6216 {
6217 $Incompatibility = "Base type of member <b>$Target</b> has been changed from <span style='white-space:nowrap;'><b>$Old_Value</b> (<b>$Old_Size</b> bytes)</span> to <span style='white-space:nowrap;'><b>$New_Value</b> (<b>$New_Size</b> bytes)</span>.";
6218 $Effect = "Layout of structure members has been changed and therefore members in higher positions in structure definition may be incorrectly accessed by applications.";
6219 }
6220 }
6221 elsif($Kind eq "Member_BaseType")
6222 {
6223 if($InitialType_Type eq "Pointer")
6224 {
6225 $Incompatibility = "Base type of member <b>$Target</b> (pointer) has been changed from <span style='white-space:nowrap;'><b>$Old_Value</b></span> to <span style='white-space:nowrap;'><b>$New_Value</b></span>.";
6226 $Effect = "Possible access of applications to incorrect memory via member pointer.";
6227 }
6228 else
6229 {
6230 $Incompatibility = "Base type of member <b>$Target</b> has been changed from <span style='white-space:nowrap;'><b>$Old_Value</b></span> to <span style='white-space:nowrap;'><b>$New_Value</b></span>.";
6231 $Effect = "Replacement of member base type may indicate a change in the semantic meaning of this member.";
6232 }
6233 }
6234 elsif($Kind eq "Member_PointerLevel")
6235 {
6236 $Incompatibility = "Type pointer level of member <b>$Target</b> has been changed from <b>$Old_Value</b> to <b>$New_Value</b>.";
6237 $Effect = "Possible incorrect initialization of member <b>$Target</b> by applications.";
6238 }
6239 if($Incompatibility)
6240 {
6241 $TypeProblemsReport .= "<tr><td align='center' valign='top' class='table_header'><span class='problem_num'>$ProblemNum</span></td><td align='left' valign='top'><span class='problem_body'>".$Incompatibility."</span></td><td align='left' valign='top'><span class='problem_body'>$Effect</span></td></tr>\n";
6242 $ProblemNum += 1;
6243 $Problems_Number += 1;
6244 $Kinds_Locations{$Kind}{$Location} = 1;
6245 }
6246 }
6247 }
6248 $ProblemNum -= 1;
6249 if($TypeProblemsReport)
6250 {
6251 my ($Affected_Interfaces_Header, $Affected_Interfaces) = getAffectedInterfaces($TypeName, \%Kinds_Locations);
6252 $HEADER_REPORT .= $ContentSpanStart."<span class='extension'>[+]</span> ".htmlSpecChars($TypeName)." ($ProblemNum)".$ContentSpanEnd."<br/>\n$ContentDivStart<table width='900px' cellpadding='3' cellspacing='0' class='problems_table'><tr><td align='center' width='2%' class='table_header'><span class='problem_title' style='white-space:nowrap;'></span></td><td width='47%' align='center' class='table_header'><span class='problem_sub_title'>Incompatibility</span></td><td align='center' class='table_header'><span class='problem_sub_title'>Effect</span></td></tr>$TypeProblemsReport</table>"."<span style='padding-left:10px'>$Affected_Interfaces_Header</span>$Affected_Interfaces<br/><br/>$ContentDivEnd\n";
6253 $HEADER_REPORT = insertIDs($HEADER_REPORT);
6254 }
6255 }
6256 if($HEADER_REPORT)
6257 {
6258 $TYPE_PROBLEMS .= "<span class='header_name'>$HeaderName</span><br/>\n".$HEADER_REPORT."<br/>";
6259 }
6260 }
6261 if($TYPE_PROBLEMS)
6262 {
6263 my $Notations = "";
6264 if($TYPE_PROBLEMS =~ /'RetVal|'Obj/)
6265 {
6266 my @Notations_Array = ();
6267 if($TYPE_PROBLEMS =~ /'RetVal/)
6268 {
6269 @Notations_Array = (@Notations_Array, "<span style='color:#444444;padding-left:5px;'><b>RetVal</b></span> - function's return value");
6270 }
6271 if($TYPE_PROBLEMS =~ /'Obj/)
6272 {
6273 @Notations_Array = (@Notations_Array, "<span style='color:#444444;'><b>Obj</b></span> - method's object (C++)");
6274 }
6275 $Notations = "Shorthand notations: ".join("; ", @Notations_Array).".<br/>\n";
6276 }
6277 $TYPE_PROBLEMS = "<a name=\'Type_Problems_$TargetPriority\'></a>\n<h2 style='margin-bottom:0px;padding-bottom:0px;'>Problems in Data Types, $TargetPriority risk ($Problems_Number)</h2><hr/>\n".$Notations."<!--Type_Problems_".$TargetPriority."-->\n".$TYPE_PROBLEMS."<!--Type_Problems_".$TargetPriority."_End-->\n"."<input id=\'Type_Problems_$TargetPriority"."_Count"."\' type='hidden' value=\'$Problems_Number\' /><a style='font-size:11px;' href='#Top'>to the top</a><br/>\n";
6278 }
6279 return $TYPE_PROBLEMS;
6280 }
6281
6282 my $ContentSpanStart_2 = "<span style='line-height:25px;' class=\"section_2\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
6283
6284 sub getAffectedInterfaces($$)
6285 {
6286 my ($Target_TypeName, $Kinds_Locations) = @_;
6287 my ($Affected_Interfaces_Header, $Affected_Interfaces, %FunctionNumber) = ();
6288 foreach my $Interface (sort {lc($tr_name{$a}) cmp lc($tr_name{$b})} keys(%CompatProblems))
6289 {
6290 next if(($Interface =~ /C2/) or ($Interface =~ /D2/) or ($Interface =~ /D0/));
6291 next if(keys(%FunctionNumber)>1000);
6292 my $FunctionProblem = "";
6293 my $MinPath_Length = "";
6294 my $MaxPriority = 0;
6295 my $Location_Last = "";
6296 foreach my $Kind (keys(%{$CompatProblems{$Interface}}))
6297 {
6298 foreach my $Location (keys(%{$CompatProblems{$Interface}{$Kind}}))
6299 {
6300 next if(not $Kinds_Locations->{$Kind}{$Location});
6301 my $Type_Name = $CompatProblems{$Interface}{$Kind}{$Location}{"Type_Name"};
6302 my $Signature = $CompatProblems{$Interface}{$Kind}{$Location}{"Signature"};
6303 my $Parameter_Position = $CompatProblems{$Interface}{$Kind}{$Location}{"Parameter_Position"};
6304 my $Priority = $CompatProblems{$Interface}{$Kind}{$Location}{"Priority"};
6305 if($Type_Name eq $Target_TypeName)
6306 {
6307 $FunctionNumber{$Interface} = 1;
6308 my $Path_Length = 0;
6309 while($Location =~ /\-\>/g){$Path_Length += 1;}
6310 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 =~ /\-\>/))
6311 {
6312 $MinPath_Length = $Path_Length;
6313 $MaxPriority = $Priority_Value{$Priority};
6314 $Location_Last = $Location;
6315 my $Description = get_AffectDescription($Interface, $Kind, $Location);
6316 $FunctionProblem = "<span class='interface_name_black' style='padding-left:20px;'>".highLight_Signature_PPos_Italic(htmlSpecChars($Signature), $Parameter_Position, 1, 0)."</span>:<br/>"."<span class='affect_description'>".addArrows($Description)."</span><br/><div style='height:4px;'>&nbsp;</div>\n";
6317 }
6318 }
6319 }
6320 }
6321 $Affected_Interfaces .= $FunctionProblem;
6322 }
6323 $Affected_Interfaces .= "and other...<br/>" if(keys(%FunctionNumber)>5000);
6324 if($Affected_Interfaces)
6325 {
6326 $Affected_Interfaces_Header = $ContentSpanStart_2."[+] affected interfaces (".keys(%FunctionNumber).")".$ContentSpanEnd;
6327 $Affected_Interfaces = $ContentDivStart.$Affected_Interfaces.$ContentDivEnd;
6328 }
6329 return ($Affected_Interfaces_Header, $Affected_Interfaces);
6330 }
6331
6332 my %Kind_TypeStructureChanged=(
6333 "Size"=>1,
6334 "Added_Member_And_Size"=>1,
6335 "Added_Middle_Member_And_Size"=>1,
6336 "Member_Rename"=>1,
6337 "Withdrawn_Member_And_Size"=>1,
6338 "Withdrawn_Member"=>1,
6339 "Withdrawn_Middle_Member_And_Size"=>1,
6340 "Enum_Member_Value"=>1,
6341 "Enum_Member_Name"=>1,
6342 "Member_Type_And_Size"=>1,
6343 "Member_Type"=>1,
6344 "Member_BaseType_And_Size"=>1,
6345 "Member_BaseType"=>1,
6346 "Member_PointerLevel"=>1,
6347 "BaseType"=>1
6348 );
6349
6350 my %Kind_VirtualTableChanged=(
6351 "Added_Virtual_Function"=>1,
6352 "Withdrawn_Virtual_Function"=>1,
6353 "Virtual_Function_Position"=>1,
6354 "Virtual_Function_Redefinition"=>1,
6355 "Virtual_Function_Redefinition_B"=>1
6356 );
6357
6358 sub get_AffectDescription($$$)
6359 {
6360 my ($Interface, $Kind, $Location) = @_;
6361 my $Target = $CompatProblems{$Interface}{$Kind}{$Location}{"Target"};
6362 my $Old_Value = $CompatProblems{$Interface}{$Kind}{$Location}{"Old_Value"};
6363 my $New_Value = $CompatProblems{$Interface}{$Kind}{$Location}{"New_Value"};
6364 my $Type_Name = $CompatProblems{$Interface}{$Kind}{$Location}{"Type_Name"};
6365 my $Parameter_Position = $CompatProblems{$Interface}{$Kind}{$Location}{"Parameter_Position"};
6366 my $Parameter_Name = $CompatProblems{$Interface}{$Kind}{$Location}{"Parameter_Name"};
6367 my $Parameter_Type_Name = $CompatProblems{$Interface}{$Kind}{$Location}{"Parameter_Type_Name"};
6368 my $Member_Type_Name = $CompatProblems{$Interface}{$Kind}{$Location}{"Member_Type_Name"};
6369 my $Object_Type_Name = $CompatProblems{$Interface}{$Kind}{$Location}{"Object_Type_Name"};
6370 my $Return_Type_Name = $CompatProblems{$Interface}{$Kind}{$Location}{"Return_Type_Name"};
6371 my $Start_Type_Name = $CompatProblems{$Interface}{$Kind}{$Location}{"Start_Type_Name"};
6372 my $InitialType_Type = $CompatProblems{$Interface}{$Kind}{$Location}{"InitialType_Type"};
6373 my $Parameter_Position_Str = num_to_str($Parameter_Position + 1);
6374 my @Sentence_Parts = ();
6375 my $Location_To_Type = $Location;
6376 $Location_To_Type =~ s/\-\>[^>]+?\Z//;
6377 if($Kind_VirtualTableChanged{$Kind})
6378 {
6379 if($Kind eq "Virtual_Function_Redefinition")
6380 {
6381 @Sentence_Parts = (@Sentence_Parts, "This method become virtual and will be called instead of redefined method '".highLight_Signature(htmlSpecChars($Old_Value))."'.");
6382 }
6383 elsif($Kind eq "Virtual_Function_Redefinition_B")
6384 {
6385 @Sentence_Parts = (@Sentence_Parts, "This method become non-virtual and redefined method '".highLight_Signature(htmlSpecChars($Old_Value))."' will be called instead of it.");
6386 }
6387 else
6388 {
6389 @Sentence_Parts = (@Sentence_Parts, "Call of this virtual method will result in crash of application because the layout of virtual table has been changed.");
6390 }
6391 }
6392 elsif($Kind_TypeStructureChanged{$Kind})
6393 {
6394 if($Location_To_Type =~ /RetVal/)
6395 {#return value
6396 if($Location_To_Type =~ /\-\>/)
6397 {
6398 @Sentence_Parts = (@Sentence_Parts, "Member \'$Location_To_Type\' in return value");
6399 }
6400 else
6401 {
6402 @Sentence_Parts = (@Sentence_Parts, "Return value");
6403 }
6404 }
6405 elsif($Location_To_Type =~ /Obj/)
6406 {#object
6407 if($Location_To_Type =~ /\-\>/)
6408 {
6409 @Sentence_Parts = (@Sentence_Parts, "Member \'$Location_To_Type\' in the object of this method");
6410 }
6411 else
6412 {
6413 @Sentence_Parts = (@Sentence_Parts, "Object");
6414 }
6415 }
6416 else
6417 {#parameters
6418 if($Location_To_Type =~ /\-\>/)
6419 {
6420 @Sentence_Parts = (@Sentence_Parts, "Member \'$Location_To_Type\' of $Parameter_Position_Str parameter");
6421 }
6422 else
6423 {
6424 @Sentence_Parts = (@Sentence_Parts, "$Parameter_Position_Str parameter");
6425 }
6426 if($Parameter_Name)
6427 {
6428 @Sentence_Parts = (@Sentence_Parts, "\'$Parameter_Name\'");
6429 }
6430 if($InitialType_Type eq "Pointer")
6431 {
6432 @Sentence_Parts = (@Sentence_Parts, "(pointer)");
6433 }
6434 }
6435 if($Start_Type_Name eq $Type_Name)
6436 {
6437 @Sentence_Parts = (@Sentence_Parts, "has type \'$Type_Name\'.");
6438 }
6439 else
6440 {
6441 @Sentence_Parts = (@Sentence_Parts, "has base type \'$Type_Name\'.");
6442 }
6443 }
6444 return join(" ", @Sentence_Parts);
6445 }
6446
6447 sub create_HtmlReport()
6448 {
6449 my $CssStyles = "<style type=\"text/css\">
6450 body{font-family:Arial;}
6451 hr{color:Black;background-color:Black;height:1px;border:0;}
6452 span.section{font-weight:bold;cursor:pointer;margin-left:7px;font-size:16px;font-family:Arial;color:#003E69;}
6453 span:hover.section{color:#336699;}
6454 span.section_2{cursor:pointer;margin-left:7px;font-size:14px;font-family:Arial;color:#cc3300;}
6455 span.extension{font-weight:100;font-size:16px;}
6456 span.problem_exact_location{color:Red;font-size:14px;}
6457 span.header_name{color:#cc3300;font-size:14px;font-family:Arial;font-weight:bold;}
6458 span.header_list_elem{padding-left:10px;color:#333333;font-size:15px;font-family:Arial;}
6459 span.solib_list_elem{padding-left:10px;color:#333333;font-size:15px;font-family:Arial;}
6460 span.solib_name{color:Green;font-size:14px;font-family:Arial;font-weight:bold;}
6461 span.interface_name{font-weight:bold;font-size:16px;font-family:Arial;color:#003E69;margin-left:7px;}
6462 span.interface_name_black{font-weight:bold;font-size:15px;font-family:Arial;color:#333333;}
6463 span.problem_title{color:#333333;font-weight:bold;font-size:13px;font-family:Verdana;}
6464 span.problem_sub_title{color:#333333;text-decoration:none;font-weight:bold;font-size:13px;font-family:Verdana;}
6465 span.problem_body{color:Black;font-size:14px;}
6466 span.int_p{font-weight:normal;}
6467 span.affect_description{padding-left:30px;font-size:14px;font-style:italic;line-height:13px;}
6468 table.problems_table{line-height:16px;margin-left:15px;margin-top:3px;border-collapse:collapse;}
6469 table.problems_table td{border-style:solid;border-color:Gray;border-width:1px;}
6470 td.table_header{background-color:#eeeeee;}
6471 td.summary_item{font-size:15px;font-family:Arial;text-align:left;}
6472 td.summary_item_value{padding-left:5px;padding-right:5px;width:35px;text-align:right;}
6473 span.problem_num{color:#333333;font-weight:bold;font-size:13px;font-family:Verdana;}
6474 span.mangled{padding-left:15px;font-size:13px;cursor:text;color:#444444;}
6475 span.symver{color:#555555;font-size:13px;white-space:nowrap;}
6476 span.color_param{font-style:italic;color:Brown;}
6477 span.focus_param{font-style:italic;color:Red;}</style>";
6478
6479 my $JScripts = "<script type=\"text/javascript\" language=\"JavaScript\">
6480 function showContent(header, id) {
6481 e = document.getElementById(id);
6482 if(e.style.display == 'none')
6483 {
6484 e.style.display = '';
6485 e.style.visibility = 'visible';
6486 header.innerHTML = header.innerHTML.replace(/\\\[[^0-9 ]\\\]/gi,\"[&minus;]\");
6487 }
6488 else
6489 {
6490 e.style.display = 'none';
6491 e.style.visibility = 'hidden';
6492 header.innerHTML = header.innerHTML.replace(/\\\[[^0-9 ]\\\]/gi,\"[+]\");
6493 }
6494 }</script>";
6495
6496 writeFile("$REPORT_PATH/abi_compat_report.html", "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
6497 <title>ABI compliance report for the library $TargetLibraryName from version ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." on ".getArch()."\n</title>\n<!--Styles-->\n".$CssStyles."\n<!--Styles_End-->\n"."<!--JScripts-->\n".$JScripts."\n<!--JScripts_End-->\n</head>\n<body>\n<div><a name='Top'></a>\n".get_Report_Header()."<br/>\n".get_Summary()."<br/>\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()."</div>\n"."<br/><br/><br/><hr/><div style='width:100%;font-family:Arial;font-size:11px;' align='right'><i>Generated on ".(localtime time)." for <span style='font-weight:bold'>$TargetLibraryName</span> by <a href='http://ispras.linux-foundation.org/index.php/ABI_compliance_checker'>ABI-compliance-checker</a> $ABI_COMPLIANCE_CHECKER_VERSION &nbsp;</i></div>\n<div style='height:999px;'></div>\n</body></html>");
6498 }
6499
6500 sub trivialCmp($$)
6501 {
6502 if(int($_[0]) > int($_[1]))
6503 {
6504 return 1;
6505 }
6506 elsif($_[0] eq $_[1])
6507 {
6508 return 0;
6509 }
6510 else
6511 {
6512 return -1;
6513 }
6514 }
6515
6516 sub addArrows($)
6517 {
6518 my $Text = $_[0];
6519 #$Text =~ s/\-\>/&#8594;/g;
6520 $Text =~ s/\-\>/&minus;&gt;/g;
6521 return $Text;
6522 }
6523
6524 sub insertIDs($)
6525 {
6526 my $Text = $_[0];
6527 while($Text =~ /CONTENT_ID/)
6528 {
6529 if(int($Content_Counter)%2)
6530 {
6531 $ContentID -= 1;
6532 }
6533 $Text =~ s/CONTENT_ID/c_$ContentID/;
6534 $ContentID += 1;
6535 $Content_Counter += 1;
6536 }
6537 return $Text;
6538 }
6539
6540 sub restrict_num_decimal_digits
6541 {
6542 my $num=shift;
6543 my $digs_to_cut=shift;
6544
6545 if ($num=~/\d+\.(\d){$digs_to_cut,}/)
6546 {
6547 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
6548 }
6549 return $num;
6550 }
6551
6552 sub parse_constants()
6553 {
6554 my $CurHeader = "";
6555 foreach my $String (split("\n", $ConstantsSrc{$Version}))
6556 {#detecting public and private constants using sources
6557 if($String=~/#[ \t]+\d+[ \t]+\"(.+)\"/)
6558 {
6559 $CurHeader=$1;
6560 }
6561 if($String=~/\#[ \t]*define[ \t]+([_A-Z]+)[ \t]+(.*)[ \t]*\Z/)
6562 {
6563 my ($Name, $Value) = ($1, $2);
6564 if(not $Constants{$Version}{$Name}{"Access"})
6565 {
6566 $Constants{$Version}{$Name}{"Access"} = "public";
6567 $Constants{$Version}{$Name}{"Value"} = $Value;
6568 $Constants{$Version}{$Name}{"Header"} = get_FileName($CurHeader);
6569 }
6570 }
6571 elsif($String=~/\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/)
6572 {
6573 my $Name = $1;
6574 $Constants{$Version}{$Name}{"Access"} = "private";
6575 }
6576 }
6577 foreach my $Constant (keys(%{$Constants{$Version}}))
6578 {
6579 if(($Constants{$Version}{$Constant}{"Access"} eq "private") or not $Constants{$Version}{$Constant}{"Value"}
6580 or $Constant=~/_h\Z/i)
6581 {
6582 delete($Constants{$Version}{$Constant});
6583 }
6584 else
6585 {
6586 delete($Constants{$Version}{$Constant}{"Access"});
6587 }
6588 }
6589 }
6590
6591 sub mergeConstants()
6592 {
6593 return if(defined $AppPath);
6594 foreach my $Constant (keys(%{$Constants{1}}))
6595 {
6596 my $Old_Value = $Constants{1}{$Constant}{"Value"};
6597 my $New_Value = $Constants{2}{$Constant}{"Value"};
6598 my $Header = $Constants{1}{$Constant}{"Header"};
6599 if($New_Value and $Old_Value and ($New_Value ne $Old_Value))
6600 {
6601 %{$ConstantProblems{$Constant}} = (
6602 "Old_Value"=>$Old_Value,
6603 "New_Value"=>$New_Value,
6604 "Header"=>$Header
6605 );
6606 }
6607 }
6608 }
6609
6610 sub mergeHeaders_Separately()
6611 {
6612 system("mkdir", "-p", "header_compile_errors/".$TargetLibraryName);
6613 system("rm", "-fr", $ERR_PATH{1}, $ERR_PATH{2});
6614 my ($Header_Num, $Prev_Header_Length) = (0, 0);
6615 my $All_Count = keys(%{$Headers{1}});
6616 foreach my $Header_Dest (sort {int($Headers{1}{$a}{"Position"})<=>int($Headers{1}{$b}{"Position"})} keys(%{$Headers{1}}))
6617 {
6618 my $Header_Name = $Headers{1}{$Header_Dest}{"Name"};
6619 my $Dest_Count = keys(%{$HeaderName_Destinations{1}{$Header_Name}});
6620 my $Identity = $Headers{1}{$Header_Dest}{"Identity"};
6621 my $Dest_Comment = ($Dest_Count>1 and $Identity=~/\//)?" ($Identity)":"";
6622 print get_one_step_title($Header_Name.$Dest_Comment, $Header_Num, $All_Count, $Prev_Header_Length, 1)."\r";
6623 %TypeDescr = ();
6624 %FuncDescr = ();
6625 %ClassFunc = ();
6626 %ClassVirtFunc = ();
6627 %LibInfo = ();
6628 %CompleteSignature = ();
6629 %Cache = ();
6630 $Version = 1;
6631 parseHeader($Header_Dest);
6632 $Version = 2;
6633 my $PairHeaderDest = find_pair_header($Header_Dest);
6634 if(not $PairHeaderDest)
6635 {
6636 $Header_Num += 1;
6637 next;
6638 }
6639 parseHeader($PairHeaderDest);
6640 mergeSignatures();
6641 mergeConstants();
6642 $Header_Num += 1;
6643 $Prev_Header_Length = length($Header_Name.$Dest_Comment);
6644 }
6645 print get_one_step_title("", $All_Count, $All_Count, $Prev_Header_Length, 0)."\n";
6646 }
6647
6648 sub get_one_step_title($$$$$)
6649 {
6650 my ($Header_Name, $Num, $All_Count, $SpacesAtTheEnd, $ShowCurrent) = @_;
6651 my ($Spaces_1, $Spaces_2, $Title) = ();
6652 my $Title_1 = "checking headers: $Num/$All_Count [".restrict_num_decimal_digits($Num*100/$All_Count, 3)."%]".(($ShowCurrent)?",":"");
6653 foreach (0 .. length("checking headers: ")+length($All_Count)*2+11 - length($Title_1))
6654 {
6655 $Spaces_1 .= " ";
6656 }
6657 $Title .= $Title_1.$Spaces_1;
6658 if($ShowCurrent)
6659 {
6660 my $Title_2 = "current: $Header_Name";
6661 foreach (0 .. $SpacesAtTheEnd - length($Header_Name)-1)
6662 {
6663 $Spaces_2 .= " ";
6664 }
6665 $Title .= $Title_2.$Spaces_2;
6666 }
6667 else
6668 {
6669 foreach (0 .. $SpacesAtTheEnd + length(" current: ") - 1)
6670 {
6671 $Title .= " ";
6672 }
6673 }
6674 return $Title."\r";
6675 }
6676
6677 sub find_pair_header($)
6678 {
6679 my $Header_Dest = $_[0];
6680 my $Header_Name = $Headers{1}{$Header_Dest}{"Name"};
6681 my $Identity = $Headers{1}{$Header_Dest}{"Identity"};
6682 my @Pair_Dest = keys(%{$HeaderName_Destinations{2}{$Header_Name}});
6683 if($#Pair_Dest==0)
6684 {
6685 return $Pair_Dest[0];
6686 }
6687 elsif($#Pair_Dest==-1)
6688 {
6689 return "";
6690 }
6691 else
6692 {
6693 foreach my $Pair_Dest (@Pair_Dest)
6694 {
6695 my $Pair_Identity = $Headers{2}{$Pair_Dest}{"Identity"};
6696 if($Identity eq $Pair_Identity)
6697 {
6698 return $Pair_Dest;
6699 }
6700 }
6701 return "";
6702 }
6703 }
6704
6705 sub getSymbols($)
6706 {
6707 my $LibVersion = $_[0];
6708 my @SoLibPaths = getSoPaths($LibVersion);
6709 if($#SoLibPaths eq -1 and not $CheckHeadersOnly)
6710 {
6711 print "ERROR: shared objects were not found\n";
6712 exit(1);
6713 }
6714 foreach my $SoLibPath (@SoLibPaths)
6715 {
6716 getSymbols_Lib($LibVersion, $SoLibPath, 0);
6717 }
6718 }
6719
6720 sub separatePath($)
6721 {
6722 return ("", $_[0])if($_[0] !~ /\//);
6723 if($_[0] =~ /\A(.*\/)([^\/]*)\Z/)
6724 {
6725 return ($1, $2);
6726 }
6727 else
6728 {
6729 return ("", $_[0]);
6730 }
6731 }
6732
6733 sub translateSymbols($)
6734 {
6735 my $LibVersion = $_[0];
6736 my (@MnglNames, @UnMnglNames) = ();
6737 foreach my $Interface (sort keys(%{$Interface_Library{$LibVersion}}))
6738 {
6739 if($Interface =~ /\A_Z/)
6740 {
6741 $Interface =~ s/[\@]+(.*)\Z//;
6742 push(@MnglNames, $Interface);
6743 }
6744 else
6745 {
6746 $tr_name{$Interface} = $Interface;
6747 $mangled_name{$tr_name{$Interface}} = $Interface;
6748 }
6749 }
6750 if($#MnglNames > -1)
6751 {
6752 @UnMnglNames = reverse(unmangleArray(@MnglNames));
6753 foreach my $Interface (sort keys(%{$Interface_Library{$LibVersion}}))
6754 {
6755 if($Interface =~ /\A_Z/)
6756 {
6757 $Interface =~ s/[\@]+(.*)\Z//;
6758 $tr_name{$Interface} = pop(@UnMnglNames);
6759 $mangled_name{correctName($tr_name{$Interface})} = $Interface;
6760 }
6761 }
6762 }
6763 }
6764
6765 sub detectAdded()
6766 {
6767 #detecting added
6768 foreach my $Interface (keys(%{$Interface_Library{2}}))
6769 {
6770 if(not $Interface_Library{1}{$Interface})
6771 {
6772 $AddedInt{$Interface} = 1;
6773 my ($MnglName, $SymbolVersion) = ($Interface, "");
6774 if($Interface =~ /\A(.+)[\@]+(.+)\Z/)
6775 {
6776 ($MnglName, $SymbolVersion) = ($1, $2);
6777 }
6778 $FuncAttr{2}{$Interface}{"Signature"} = $tr_name{$MnglName}.(($SymbolVersion)?"\@".$SymbolVersion:"");
6779 }
6780 }
6781 }
6782
6783 sub detectWithdrawn()
6784 {
6785 #detecting withdrawn
6786 foreach my $Interface (keys(%{$Interface_Library{1}}))
6787 {
6788 if(not $Interface_Library{2}{$Interface} and not $Interface_Library{2}{$SymVer{2}{$Interface}})
6789 {
6790 next if($DepInterfaces{2}{$Interface});
6791 $WithdrawnInt{$Interface} = 1;
6792 my ($MnglName, $SymbolVersion) = ($Interface, "");
6793 if($Interface =~ /\A(.+)[\@]+(.+)\Z/)
6794 {
6795 ($MnglName, $SymbolVersion) = ($1, $2);
6796 }
6797 $FuncAttr{1}{$Interface}{"Signature"} = $tr_name{$MnglName}.(($SymbolVersion)?"\@".$SymbolVersion:"");
6798 }
6799 }
6800 }
6801
6802 sub isRecurLib($)
6803 {
6804 my $LibName = $_[0];
6805 foreach my $LibNameInStack (@RecurLib)
6806 {
6807 if($LibName eq $LibNameInStack)
6808 {
6809 return 1;
6810 }
6811 }
6812 return 0;
6813 }
6814
6815 sub getSymbols_App($)
6816 {
6817 my $Path = $_[0];
6818 return () if(not $Path or not -f $Path);
6819 my @Ints = ();
6820 open(APP, "readelf -WhlSsdA $Path |");
6821 my $symtab=0;#indicates that we are processing 'symtab' section of 'readelf' output
6822 while(<APP>)
6823 {
6824 if($symtab == 1) {
6825 #do nothing with symtab (but there are some plans for the future)
6826 next;
6827 }
6828 if( /'.dynsym'/ ) {
6829 $symtab=0;
6830 }
6831 elsif( /'.symtab'/ ) {
6832 $symtab=1;
6833 }
6834 elsif(my ($fullname, $idx, $Ndx) = readlile_ELF($_)) {
6835 if( $Ndx eq "UND" ) {
6836 #only exported interfaces
6837 push(@Ints, $fullname);
6838 }
6839 }
6840 }
6841 close(APP);
6842 return @Ints;
6843 }
6844
6845 sub readlile_ELF($)
6846 {
6847 if($_[0]=~/\s*\d+:\s+(\w*)\s+\w+\s+(\w+)\s+(\w+)\s+(\w+)\s+(\w+)\s((\w|@|\.)+)/)
6848 {#the line of 'readelf' output corresponding to the interface
6849 my ($value, $type, $bind, $vis, $Ndx, $fullname)=($1, $2, $3, $4, $5, $6);
6850 if(($bind ne "WEAK") and ($bind ne "GLOBAL")) {
6851 return ();
6852 }
6853 if(($type ne "FUNC") and ($type ne "OBJECT") and ($type ne "COMMON")) {
6854 return ();
6855 }
6856 if($vis ne "DEFAULT") {
6857 return ();
6858 }
6859 if(($Ndx eq "ABS") and ($value !~ /\D|1|2|3|4|5|6|7|8|9/)) {
6860 return ();
6861 }
6862 return ($fullname, $value, $Ndx);
6863 }
6864 else
6865 {
6866 return ();
6867 }
6868 }
6869
6870 sub getSymbols_Lib($$$)
6871 {
6872 my ($LibVersion, $Lib_Path, $IsNeededLib) = @_;
6873 return if(not $Lib_Path or not -f $Lib_Path);
6874 my ($Lib_Dir, $Lib_SoName) = separatePath($Lib_Path);
6875 return if($CheckedSoLib{$LibVersion}{$Lib_SoName} and $IsNeededLib);
6876 return if(isRecurLib($Lib_SoName) or $#RecurLib>=1);
6877 $CheckedSoLib{$LibVersion}{$Lib_SoName} = 1;
6878 push(@RecurLib, $Lib_SoName);
6879 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
6880 if(not $IsNeededLib)
6881 {
6882 $SoNames_All{$LibVersion}{$Lib_SoName} = 1;
6883 }
6884 open(SOLIB, "readelf -WhlSsdA $Lib_Path |");
6885 my $symtab=0;#indicates that we are processing 'symtab' section of 'readelf' output
6886 while(<SOLIB>)
6887 {
6888 if($symtab == 1) {
6889 #do nothing with symtab (but there are some plans for the future)
6890 next;
6891 }
6892 if(/'.dynsym'/) {
6893 $symtab=0;
6894 }
6895 elsif(/'.symtab'/) {
6896 $symtab=1;
6897 }
6898 elsif(/NEEDED.+\[([^\[\]]+)\]/)
6899 {
6900 $NeededLib{$1} = 1;
6901 }
6902 elsif(my ($fullname, $idx, $Ndx) = readlile_ELF($_)) {
6903 if( $Ndx eq "UND" ) {
6904 #ignore interfaces that are exported form somewhere else
6905 next;
6906 }
6907 my ($realname, $version) = ($fullname, "");
6908 if($fullname =~ /\A([^@]+)[\@]+([^@]+)\Z/)
6909 {
6910 ($realname, $version) = ($1, $2);
6911 }
6912 next if(defined $InterfacesListPath and not $InterfacesList{$realname});
6913 next if(defined $AppPath and not $InterfacesList_App{$realname});
6914 if($IsNeededLib)
6915 {
6916 $DepInterfaces{$LibVersion}{$fullname} = 1;
6917 }
6918 if(not $IsNeededLib or (defined $InterfacesListPath and $InterfacesList{$realname}) or (defined $AppPath and $InterfacesList_App{$realname}))
6919 {
6920 $Interface_Library{$LibVersion}{$fullname} = $Lib_SoName;
6921 $Library_Interface{$LibVersion}{$Lib_SoName}{$fullname} = 1;
6922 $Interface_Value{$LibVersion}{$fullname} = $idx;
6923 $Value_Interface{$LibVersion}{$idx}{$fullname} = 1;
6924 if(not $Language{$LibVersion}{$Lib_SoName})
6925 {
6926 if($fullname =~ /\A_Z[A-Z]*[0-9]+/)
6927 {
6928 $Language{$LibVersion}{$Lib_SoName} = "C++";
6929 }
6930 }
6931 }
6932 }
6933 }
6934 close(SOLIB);
6935 if(not $IsNeededLib)
6936 {
6937 foreach my $Interface_Name (keys(%{$Interface_Library{$LibVersion}}))
6938 {
6939 next if($Interface_Name !~ /\@/);
6940 my $Interface_SymName = "";
6941 foreach my $InterfaceName_SameValue (keys(%{$Value_Interface{$LibVersion}{$Interface_Value{$LibVersion}{$Interface_Name}}}))
6942 {
6943 if($InterfaceName_SameValue ne $Interface_Name)
6944 {
6945 $SymVer{$LibVersion}{$InterfaceName_SameValue} = $Interface_Name;
6946 $Interface_SymName = $InterfaceName_SameValue;
6947 last;
6948 }
6949 }
6950 if(not $Interface_SymName)
6951 {
6952 if($Interface_Name =~ /\A([^@]*)[\@]+([^@]*)\Z/ and not $SymVer{$LibVersion}{$1})
6953 {
6954 $SymVer{$LibVersion}{$1} = $Interface_Name;
6955 }
6956 }
6957 }
6958 }
6959 foreach my $SoLib (keys(%NeededLib))
6960 {
6961 getSymbols_Lib($LibVersion, find_solib_path($Lib_Dir, $SoLib), 1);
6962 }
6963 pop(@RecurLib);
6964 }
6965
6966 sub find_solib_path($$)
6967 {
6968 my ($Dir, $SoName) = @_;
6969 $Dir=~s/\/\Z//g;
6970 if(-f $Dir."/".$SoName)
6971 {
6972 return $Dir."/".$SoName;
6973 }
6974 else
6975 {
6976 return $SoLib_DefaultPath{$SoName};
6977 }
6978 }
6979
6980 sub symbols_Preparation($)
6981 {#recreate %SoNames and %Language using info from *.abi file
6982 my $LibVersion = $_[0];
6983 foreach my $Lib_SoName (keys(%{$Library_Interface{$LibVersion}}))
6984 {
6985 foreach my $Interface_Name (keys(%{$Library_Interface{$LibVersion}{$Lib_SoName}}))
6986 {
6987 $Interface_Library{$LibVersion}{$Interface_Name} = $Lib_SoName;
6988 $SoNames_All{$LibVersion}{$Lib_SoName} = 1;
6989 if(not $Language{$LibVersion}{$Lib_SoName})
6990 {
6991 if($Interface_Name =~ /\A_Z[A-Z]*[0-9]+/)
6992 {
6993 $Language{$LibVersion}{$Lib_SoName} = "C++";
6994 }
6995 }
6996 }
6997 }
6998 }
6999
7000 sub getSoPaths($)
7001 {
7002 my $LibVersion = $_[0];
7003 my @SoPaths = ();
7004 foreach my $Dest (split("\n", $Descriptor{$LibVersion}{"Libs"}))
7005 {
7006 $Dest =~ s/\A\s+|\s+\Z//g;
7007 next if(not $Dest);
7008 if(not -e $Dest)
7009 {
7010 print "ERROR: can't access \'$Dest\'\n";
7011 }
7012 my @SoPaths_Dest = getSOPaths_Dest($Dest);
7013 foreach (@SoPaths_Dest)
7014 {
7015 push(@SoPaths, $_);
7016 }
7017 }
7018 return @SoPaths;
7019 }
7020
7021 sub getSOPaths_Dest($)
7022 {
7023 my $Dest = $_[0];
7024 if(-f $Dest)
7025 {
7026 return $Dest;
7027 }
7028 my @AllObjects = cmd_find($Dest,"f","*\.so*");
7029 my @SOPaths = ();
7030 foreach my $SharedObject (@AllObjects)
7031 {
7032 if(cmd_file($SharedObject) =~ /shared object/)
7033 {
7034 @SOPaths = (@SOPaths, $SharedObject);
7035 }
7036 }
7037 return @SOPaths;
7038 }
7039
7040 sub genDescriptorTemplate()
7041 {
7042 writeFile("library-descriptor.xml", $Descriptor_Template."\n");
7043 print "descriptor template named 'library-descriptor.xml' has been generated in the current directory\n";
7044 }
7045
7046 sub detectPointerSize()
7047 {
7048 `mkdir -p temp`;
7049 writeFile("temp/get_pointer_size.c", "#include <stdio.h>
7050 int main()
7051 {
7052 printf(\"\%d\", sizeof(int*));
7053 return 0;
7054 }\n");
7055 system("gcc temp/get_pointer_size.c -o temp/get_pointer_size");
7056 $POINTER_SIZE = `./temp/get_pointer_size`;
7057 `rm -fr temp`;
7058 }
7059
7060 sub data_Preparation($)
7061 {
7062 my $LibVersion = $_[0];
7063 if($Descriptor{$LibVersion}{"Path"} =~ /\.abi\.tar\.gz/)
7064 {
7065 my $FileName = cmd_tar($Descriptor{$LibVersion}{"Path"});
7066 if($FileName =~ /\.abi/)
7067 {
7068 chomp($FileName);
7069 my $LibraryABI = eval readFile($FileName);
7070 system("rm", "-f", $FileName);
7071 $TypeDescr{$LibVersion} = $LibraryABI->{"TypeDescr"};
7072 $FuncDescr{$LibVersion} = $LibraryABI->{"FuncDescr"};
7073 $Library_Interface{$LibVersion} = $LibraryABI->{"Interfaces"};
7074 $SymVer{$LibVersion} = $LibraryABI->{"SymVer"};
7075 $Tid_TDid{$LibVersion} = $LibraryABI->{"Tid_TDid"};
7076 $Descriptor{$LibVersion}{"Version"} = $LibraryABI->{"LibraryVersion"};
7077 $OpaqueTypes{$LibVersion} = $LibraryABI->{"OpaqueTypes"};
7078 $InternalInterfaces{$LibVersion} = $LibraryABI->{"InternalInterfaces"};
7079 $Headers{$LibVersion} = $LibraryABI->{"Headers"};
7080 $SoNames_All{$LibVersion} = $LibraryABI->{"SharedObjects"};
7081 $Constants{$LibVersion} = $LibraryABI->{"Constants"};
7082 if($LibraryABI->{"ABI_COMPLIANCE_CHECKER_VERSION"} ne $ABI_COMPLIANCE_CHECKER_VERSION)
7083 {
7084 print "ERROR: incompatible version of specified ABI dump (allowed only $ABI_COMPLIANCE_CHECKER_VERSION)\n";
7085 exit(1);
7086 }
7087 foreach my $Destination (keys(%{$Headers{$LibVersion}}))
7088 {
7089 my $Header = get_FileName($Destination);
7090 $HeaderName_Destinations{$LibVersion}{$Header}{$Destination} = 1;
7091 }
7092 symbols_Preparation($LibVersion);
7093 }
7094 }
7095 elsif($Descriptor{$LibVersion}{"Path"} =~ /\.tar\.gz\Z/)
7096 {
7097 print "ERROR: descriptor must be an XML file or '*.abi.tar.gz' ABI dump\n";
7098 exit(1);
7099 }
7100 else
7101 {
7102 readDescriptor($LibVersion);
7103 if(not $CheckHeadersOnly)
7104 {
7105 getSymbols($LibVersion);
7106 }
7107 headerSearch($LibVersion);
7108 }
7109 }
7110
7111 sub dump_sorting($)
7112 {
7113 my $hash = $_[0];
7114 if((keys(%{$hash}))[0] =~ /\A[0-9]+\Z/)
7115 {
7116 return [sort {int($a) <=> int($b)} keys %{$hash}];
7117 }
7118 else
7119 {
7120 return [sort {$a cmp $b} keys %{$hash}];
7121 }
7122 }
7123
7124 sub get_solib_default_paths()
7125 {
7126 foreach my $Line (split("\n", `ldconfig -p`))
7127 {
7128 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
7129 {
7130 $SoLib_DefaultPath{$1} = $2;
7131 }
7132 }
7133 }
7134
7135 sub scenario()
7136 {
7137 if(defined $Help)
7138 {
7139 HELP_MESSAGE();
7140 exit(0);
7141 }
7142 if(defined $ShowVersion)
7143 {
7144 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 <http://www.gnu.org/licenses/>\nThis program is free software: you can redistribute it and/or modify it.\n\nWritten by Andrey Ponomarenko.\n";
7145 exit(0);
7146 }
7147 $Data::Dumper::Sortkeys = \&dump_sorting;
7148 if(defined $TestSystem)
7149 {
7150 testSystem_cpp();
7151 testSystem_c();
7152 exit(0);
7153 }
7154 if($GenerateDescriptor)
7155 {
7156 genDescriptorTemplate();
7157 exit(0);
7158 }
7159 if(not defined $TargetLibraryName)
7160 {
7161 print "select library name (option -l <name>)\n";
7162 exit(1);
7163 }
7164 if(defined $InterfacesListPath)
7165 {
7166 if(not -f $InterfacesListPath)
7167 {
7168 print "ERROR: can't access file $InterfacesListPath\n";
7169 exit(1);
7170 }
7171 foreach my $Interface (split("\n", readFile($InterfacesListPath)))
7172 {
7173 $InterfacesList{$Interface} = 1;
7174 }
7175 }
7176 if($AppPath)
7177 {
7178 if(-f $AppPath)
7179 {
7180 foreach my $Interface (getSymbols_App($AppPath))
7181 {
7182 $InterfacesList_App{$Interface} = 1;
7183 }
7184 }
7185 else
7186 {
7187 print "ERROR: can't access file \'$AppPath\'\n";
7188 exit(1);
7189 }
7190 }
7191 get_solib_default_paths();
7192 if($DumpInfo_DescriptorPath)
7193 {
7194 if(not -f $DumpInfo_DescriptorPath)
7195 {
7196 print "ERROR: can't access file \'$DumpInfo_DescriptorPath\'\n";
7197 exit(1);
7198 }
7199 $Descriptor{1}{"Path"} = $DumpInfo_DescriptorPath;
7200 readDescriptor(1);
7201 detectPointerSize();
7202 getSymbols(1);
7203 translateSymbols(1);
7204 headerSearch(1);
7205 parseHeaders_AllInOne(1);
7206 cleanData(1);
7207 my %LibraryABI = ();
7208 print "creating library ABI info dump ...\n";
7209 $LibraryABI{"TypeDescr"} = $TypeDescr{1};
7210 $LibraryABI{"FuncDescr"} = $FuncDescr{1};
7211 $LibraryABI{"Interfaces"} = $Library_Interface{1};
7212 $LibraryABI{"SymVer"} = $SymVer{1};
7213 $LibraryABI{"LibraryVersion"} = $Descriptor{1}{"Version"};
7214 $LibraryABI{"Library"} = $TargetLibraryName;
7215 $LibraryABI{"SharedObjects"} = $SoNames_All{1};
7216 $LibraryABI{"Tid_TDid"} = $Tid_TDid{1};
7217 $LibraryABI{"OpaqueTypes"} = $OpaqueTypes{1};
7218 $LibraryABI{"InternalInterfaces"} = $InternalInterfaces{1};
7219 $LibraryABI{"Headers"} = $Headers{1};
7220 $LibraryABI{"Constants"} = $Constants{1};
7221 $LibraryABI{"ABI_COMPLIANCE_CHECKER_VERSION"} = $ABI_COMPLIANCE_CHECKER_VERSION;
7222 my $InfoDump_FilePath = "abi_dumps/$TargetLibraryName";
7223 my $InfoDump_FileName = $TargetLibraryName."_".$Descriptor{1}{"Version"}.".abi";
7224 system("mkdir", "-p", $InfoDump_FilePath);
7225 system("rm", "-f", $InfoDump_FilePath."/".$InfoDump_FileName.".tar.gz");
7226 writeFile("$InfoDump_FilePath/$InfoDump_FileName", Dumper(\%LibraryABI));
7227 system("cd ".esc($InfoDump_FilePath)." && tar -cf ".esc($InfoDump_FileName).".tar ".esc($InfoDump_FileName));
7228 system("cd ".esc($InfoDump_FilePath)." && gzip ".esc($InfoDump_FileName).".tar --best");
7229 system("rm", "-f", $InfoDump_FilePath."/".$InfoDump_FileName);
7230 if($?)
7231 {
7232 print "ERROR: can't create library ABI info dump\n";
7233 exit(1);
7234 }
7235 else
7236 {
7237 print "see library ABI info dump in \'$InfoDump_FilePath/$InfoDump_FileName\.tar\.gz\': use it instead of library version descriptor on other machine\n";
7238 exit(0);
7239 }
7240 }
7241 if(not $Descriptor{1}{"Path"})
7242 {
7243 print "select 1st library descriptor (option -d1 <path>)\n";
7244 exit(1);
7245 }
7246 if(not -f $Descriptor{1}{"Path"})
7247 {
7248 print "ERROR: descriptor d1 does not exist, incorrect file path '".$Descriptor{1}{"Path"}."'\n";
7249 exit(1);
7250 }
7251 if(not $Descriptor{2}{"Path"})
7252 {
7253 print "select 2nd library descriptor (option -d2 <path>)\n";
7254 exit(1);
7255 }
7256 if(not -f $Descriptor{2}{"Path"})
7257 {
7258 print "ERROR: descriptor d2 does not exist, incorrect file path '".$Descriptor{2}{"Path"}."'\n";
7259 exit(1);
7260 }
7261 $StartTime = localtime time;
7262 print "preparation...\n";
7263 data_Preparation(1);
7264 data_Preparation(2);
7265 if($AppPath and not keys(%{$Interface_Library{1}}))
7266 {
7267 print "WARNING: symbols from the specified application were not found in the specified library shared objects\n";
7268 }
7269 $REPORT_PATH = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
7270 system("mkdir", "-p", $REPORT_PATH);
7271 system("rm", "-f", $REPORT_PATH."/abi_compat_report.html");
7272 detectPointerSize();
7273 translateSymbols(1);
7274 translateSymbols(2);
7275 if(not $CheckHeadersOnly)
7276 {
7277 detectAdded();
7278 detectWithdrawn();
7279 }
7280 #headers merging
7281 if($HeaderCheckingMode_Separately and $Descriptor{1}{"Path"} !~ /\.abi\.tar\.gz/ and $Descriptor{2}{"Path"} !~ /\.abi\.tar\.gz/)
7282 {
7283 mergeHeaders_Separately();
7284 }
7285 else
7286 {
7287 if($Descriptor{1}{"Path"} !~ /\.abi\.tar\.gz/)
7288 {
7289 parseHeaders_AllInOne(1);
7290 }
7291 if($Descriptor{2}{"Path"} !~ /\.abi\.tar\.gz/)
7292 {
7293 parseHeaders_AllInOne(2);
7294 }
7295 print "comparing headers ...\n";
7296 mergeSignatures();
7297 mergeConstants();
7298 }
7299 #libraries merging
7300 if(not $CheckHeadersOnly)
7301 {
7302 print "comparing shared objects ...\n";
7303 mergeLibs();
7304 }
7305 print "creating ABI compliance report ...\n";
7306 create_HtmlReport();
7307 if($HeaderCheckingMode_Separately)
7308 {
7309 if(keys(%HeaderCompileError))
7310 {
7311 print "\nWARNING: compilation errors in following headers:\n";
7312 foreach my $Header (keys(%HeaderCompileError))
7313 {
7314 print $Header." ";
7315 }
7316 print "\nyou can see compilation errors in the following files:\n '$ERR_PATH{1}'\n '$ERR_PATH{2}'\n";
7317 }
7318 }
7319 `rm -fr temp`;
7320 print "\nstarted: $StartTime, finished: ".(localtime time)."\n" if($ShowExpendTime);
7321 print "see the ABI compliance report in the file '$REPORT_PATH/abi_compat_report.html'\n";
7322 exit(0);
7323 }
7324
7325 scenario();