Changeset 11682 in josm for trunk/tools


Ignore:
Timestamp:
2017-03-05T01:25:59+01:00 (8 years ago)
Author:
Don-vip
Message:

update to japi-compliance-checker 2.1

Location:
trunk/tools/japicc
Files:
22 added
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tools/japicc/japi-compliance-checker.pl

    r10845 r11682  
    11#!/usr/bin/perl
    22###########################################################################
    3 # Java API Compliance Checker (JAPICC) 1.8
     3# Java API Compliance Checker (JAPICC) 2.1
    44# A tool for checking backward compatibility of a Java library API
    55#
    66# Written by Andrey Ponomarenko
    77#
    8 # Copyright (C) 2011 Institute for System Programming, RAS
    9 # Copyright (C) 2011-2016 Andrey Ponomarenko's ABI Laboratory
     8# Copyright (C) 2011-2017 Andrey Ponomarenko's ABI Laboratory
    109#
    1110# PLATFORMS
     
    4039use File::Path qw(mkpath rmtree);
    4140use File::Temp qw(tempdir);
    42 use File::Copy qw(copy);
    43 use File::Spec::Functions qw(abs2rel);
     41use File::Basename qw(dirname);
    4442use Cwd qw(abs_path cwd);
    4543use Data::Dumper;
    46 use Digest::MD5 qw(md5_hex);
    47 use Config;
    48 
    49 my $TOOL_VERSION = "1.8";
    50 my $API_DUMP_VERSION = "2.0";
    51 my $API_DUMP_MAJOR = majorVersion($API_DUMP_VERSION);
    52 
    53 my ($Help, $ShowVersion, %Descriptor, $TargetLibraryName, $CheckSeparately,
    54 $TestSystem, $DumpAPI, $ClassListPath, $ClientPath, $StrictCompat,
    55 $DumpVersion, $BinaryOnly, $TargetTitle, %TargetVersion, $SourceOnly,
    56 $ShortMode, $KeepInternal, $OutputReportPath, $BinaryReportPath,
    57 $SourceReportPath, $Debug, $Quick, $SortDump, $SkipDeprecated, $SkipClassesList,
    58 $ShowAccess, $AffectLimit, $JdkPath, $SkipInternalPackages, $HideTemplates,
    59 $HidePackages, $ShowPackages, $Minimal, $AnnotationsListPath,
    60 $SkipPackagesList, $OutputDumpPath, $AllAffected, $Compact,
    61 $SkipAnnotationsListPath, $ExternCss, $ExternJs, $SkipInternalTypes,
    62 $AddedAnnotations, $RemovedAnnotations, $CountMethods, %DepDump, $OldStyle);
    63 
    64 my $CmdName = get_filename($0);
    65 my $OSgroup = get_OSgroup();
    66 my $ORIG_DIR = cwd();
    67 my $TMP_DIR = tempdir(CLEANUP=>1);
    68 my $ARG_MAX = get_ARG_MAX();
    69 my $REPRODUCIBLE = 1;
    70 my $MD5_LEN = 8;
    71 
    72 my %OS_Archive = (
    73     "windows"=>"zip",
    74     "default"=>"tar.gz"
    75 );
    76 
    77 my %ERROR_CODE = (
    78     # Compatible verdict
    79     "Compatible"=>0,
    80     "Success"=>0,
    81     # Incompatible verdict
    82     "Incompatible"=>1,
    83     # Undifferentiated error code
    84     "Error"=>2,
    85     # System command is not found
    86     "Not_Found"=>3,
    87     # Cannot access input files
    88     "Access_Error"=>4,
    89     # Invalid input API dump
    90     "Invalid_Dump"=>7,
    91     # Incompatible version of API dump
    92     "Dump_Version"=>8,
    93     # Cannot find a module
    94     "Module_Error"=>9
    95 );
     44
     45my $TOOL_VERSION = "2.1";
     46my $API_DUMP_VERSION = "2.1";
     47my $API_DUMP_VERSION_MIN = "2.0";
     48
     49# Internal modules
     50my $MODULES_DIR = getModules();
     51push(@INC, dirname($MODULES_DIR));
     52
     53# Basic modules
     54my %LoadedModules = ();
     55loadModule("Basic");
     56loadModule("Input");
     57loadModule("Path");
     58loadModule("Logging");
     59loadModule("Utils");
     60loadModule("TypeAttr");
     61loadModule("Filter");
     62loadModule("SysFiles");
     63loadModule("Descriptor");
     64loadModule("Mangling");
     65
     66# Rules DB
     67my %RULES_PATH = (
     68"Binary" => $MODULES_DIR."/RulesBin.xml",
     69"Source" => $MODULES_DIR."/RulesSrc.xml");
     70
     71my $CmdName = getFilename($0);
    9672
    9773my %HomePage = (
    9874    "Dev"=>"https://github.com/lvc/japi-compliance-checker",
    99     "Wiki"=>"http://ispras.linuxbase.org/index.php/Java_API_Compliance_Checker"
     75    "Doc"=>"https://lvc.github.io/japi-compliance-checker/"
    10076);
    10177
    10278my $ShortUsage = "Java API Compliance Checker (JAPICC) $TOOL_VERSION
    10379A tool for checking backward compatibility of a Java library API
    104 Copyright (C) 2016 Andrey Ponomarenko's ABI Laboratory
     80Copyright (C) 2017 Andrey Ponomarenko's ABI Laboratory
    10581License: GNU LGPL or GNU GPL
    10682
     
    11692}
    11793
    118 GetOptions("h|help!" => \$Help,
    119   "v|version!" => \$ShowVersion,
    120   "dumpversion!" => \$DumpVersion,
     94GetOptions("h|help!" => \$In::Opt{"Help"},
     95  "v|version!" => \$In::Opt{"ShowVersion"},
     96  "dumpversion!" => \$In::Opt{"DumpVersion"},
    12197# general options
    122   "l|lib|library=s" => \$TargetLibraryName,
    123   "d1|old|o=s" => \$Descriptor{1}{"Path"},
    124   "d2|new|n=s" => \$Descriptor{2}{"Path"},
     98  "l|lib|library=s" => \$In::Opt{"TargetLib"},
     99  "d1|old|o=s" => \$In::Desc{1}{"Path"},
     100  "d2|new|n=s" => \$In::Desc{2}{"Path"},
    125101# extra options
    126   "client|app=s" => \$ClientPath,
    127   "binary|bin!" => \$BinaryOnly,
    128   "source|src!" => \$SourceOnly,
    129   "v1|version1|vnum=s" => \$TargetVersion{1},
    130   "v2|version2=s" => \$TargetVersion{2},
    131   "s|strict!" => \$StrictCompat,
    132   "keep-internal!" => \$KeepInternal,
    133   "skip-internal-packages|skip-internal=s" => \$SkipInternalPackages,
    134   "skip-internal-types=s" => \$SkipInternalTypes,
    135   "dump|dump-api=s" => \$DumpAPI,
    136   "classes-list=s" => \$ClassListPath,
    137   "annotations-list=s" => \$AnnotationsListPath,
    138   "skip-annotations-list=s" => \$SkipAnnotationsListPath,
    139   "skip-deprecated!" => \$SkipDeprecated,
    140   "skip-classes=s" => \$SkipClassesList,
    141   "skip-packages=s" => \$SkipPackagesList,
    142   "short" => \$ShortMode,
    143   "dump-path=s" => \$OutputDumpPath,
    144   "report-path=s" => \$OutputReportPath,
    145   "bin-report-path=s" => \$BinaryReportPath,
    146   "src-report-path=s" => \$SourceReportPath,
    147   "quick!" => \$Quick,
    148   "sort!" => \$SortDump,
    149   "show-access!" => \$ShowAccess,
    150   "limit-affected=s" => \$AffectLimit,
    151   "hide-templates!" => \$HideTemplates,
    152   "show-packages!" => \$ShowPackages,
    153   "compact!" => \$Compact,
    154   "added-annotations!" => \$AddedAnnotations,
    155   "removed-annotations!" => \$RemovedAnnotations,
    156   "count-methods=s" => \$CountMethods,
    157   "dep1=s" => \$DepDump{1},
    158   "dep2=s" => \$DepDump{2},
    159   "old-style!" => \$OldStyle,
     102  "client|app=s" => \$In::Opt{"ClientPath"},
     103  "binary|bin!" => \$In::Opt{"BinaryOnly"},
     104  "source|src!" => \$In::Opt{"SourceOnly"},
     105  "v1|version1|vnum=s" => \$In::Desc{1}{"TargetVersion"},
     106  "v2|version2=s" => \$In::Desc{2}{"TargetVersion"},
     107  "s|strict!" => \$In::Opt{"StrictCompat"},
     108  "keep-internal!" => \$In::Opt{"KeepInternal"},
     109  "skip-internal-packages|skip-internal=s" => \$In::Opt{"SkipInternalPackages"},
     110  "skip-internal-types=s" => \$In::Opt{"SkipInternalTypes"},
     111  "dump|dump-api=s" => \$In::Opt{"DumpAPI"},
     112  "classes-list=s" => \$In::Opt{"ClassListPath"},
     113  "annotations-list=s" => \$In::Opt{"AnnotationsListPath"},
     114  "skip-annotations-list=s" => \$In::Opt{"SkipAnnotationsListPath"},
     115  "skip-deprecated!" => \$In::Opt{"SkipDeprecated"},
     116  "skip-classes=s" => \$In::Opt{"SkipClassesList"},
     117  "skip-packages=s" => \$In::Opt{"SkipPackagesList"},
     118  "short" => \$In::Opt{"ShortMode"},
     119  "dump-path=s" => \$In::Opt{"OutputDumpPath"},
     120  "report-path=s" => \$In::Opt{"OutputReportPath"},
     121  "bin-report-path=s" => \$In::Opt{"BinaryReportPath"},
     122  "src-report-path=s" => \$In::Opt{"SourceReportPath"},
     123  "quick!" => \$In::Opt{"Quick"},
     124  "sort!" => \$In::Opt{"SortDump"},
     125  "show-access!" => \$In::Opt{"ShowAccess"},
     126  "limit-affected=s" => \$In::Opt{"AffectLimit"},
     127  "hide-templates!" => \$In::Opt{"HideTemplates"},
     128  "show-packages!" => \$In::Opt{"ShowPackages"},
     129  "compact!" => \$In::Opt{"Compact"},
     130  "added-annotations!" => \$In::Opt{"AddedAnnotations"},
     131  "removed-annotations!" => \$In::Opt{"RemovedAnnotations"},
     132  "count-methods=s" => \$In::Opt{"CountMethods"},
     133  "dep1=s" => \$In::Desc{1}{"DepDump"},
     134  "dep2=s" => \$In::Desc{2}{"DepDump"},
     135  "old-style!" => \$In::Opt{"OldStyle"},
    160136# other options
    161   "test!" => \$TestSystem,
    162   "debug!" => \$Debug,
    163   "title=s" => \$TargetTitle,
    164   "jdk-path=s" => \$JdkPath,
    165   "external-css=s" => \$ExternCss,
    166   "external-js=s" => \$ExternJs,
     137  "test!" => \$In::Opt{"TestTool"},
     138  "debug!" => \$In::Opt{"Debug"},
     139  "title=s" => \$In::Opt{"TargetTitle"},
     140  "jdk-path=s" => \$In::Opt{"JdkPath"},
     141  "external-css=s" => \$In::Opt{"ExternCss"},
     142  "external-js=s" => \$In::Opt{"ExternJs"},
    167143# deprecated
    168   "minimal!" => \$Minimal,
    169   "hide-packages!" => \$HidePackages,
     144  "minimal!" => \$In::Opt{"Minimal"},
     145  "hide-packages!" => \$In::Opt{"HidePackages"},
    170146# private
    171   "all-affected!" => \$AllAffected
    172 ) or ERR_MESSAGE();
     147  "all-affected!" => \$In::Opt{"AllAffected"}
     148) or errMsg();
    173149
    174150if(@ARGV)
     
    176152    if($#ARGV==1)
    177153    { # japi-compliance-checker OLD.jar NEW.jar
    178         $Descriptor{1}{"Path"} = $ARGV[0];
    179         $Descriptor{2}{"Path"} = $ARGV[1];
     154        $In::Desc{1}{"Path"} = $ARGV[0];
     155        $In::Desc{2}{"Path"} = $ARGV[1];
    180156    }
    181157    else {
    182         ERR_MESSAGE();
    183     }
    184 }
    185 
    186 sub ERR_MESSAGE()
     158        errMsg();
     159    }
     160}
     161
     162sub errMsg()
    187163{
    188164    printMsg("INFO", "\n".$ShortUsage);
    189     exit($ERROR_CODE{"Error"});
    190 }
    191 
    192 my $AR_EXT = getAR_EXT($OSgroup);
    193 
    194 my $HelpMessage="
     165    exit(getErrorCode("Error"));
     166}
     167
     168my $HelpMessage = "
    195169NAME:
    196170  Java API Compliance Checker ($CmdName)
     
    199173DESCRIPTION:
    200174  Java API Compliance Checker (JAPICC) is a tool for checking backward
    201   binary/source compatibility of a Java library API. The tool checks classes
     175  binary/source compatibility of a Java library API. The tool checks class
    202176  declarations of old and new versions and analyzes changes that may break
    203   compatibility: removed class members, added abstract methods, etc. Breakage
    204   of the binary compatibility may result in crashing or incorrect behavior of
    205   existing clients built with an old version of a library if they run with a
    206   new one. Breakage of the source compatibility may result in recompilation
     177  compatibility: removed class members, added abstract methods, etc.
     178 
     179  Break of the binary compatibility may result in crash or incorrect behavior
     180  of existing clients built with an old library version if they run with a
     181  new one. Break of the source compatibility may result in recompilation
    207182  errors with a new library version.
    208183
    209   JAPICC is intended for library developers and operating system maintainers
    210   who are interested in ensuring backward compatibility (i.e. allow old clients
    211   to run or to be recompiled with a new version of a library).
     184  The tool is intended for developers of software libraries and maintainers
     185  of operating systems who are interested in ensuring backward compatibility,
     186  i.e. allow old clients to run or to be recompiled with newer library
     187  versions.
    212188
    213189  This tool is free software: you can redistribute it and/or modify it
     
    217193  $CmdName [options]
    218194
    219 EXAMPLE:
     195EXAMPLE 1:
    220196  $CmdName OLD.jar NEW.jar
    221     OR
     197
     198EXAMPLE 2:
    222199  $CmdName -lib NAME -old OLD.xml -new NEW.xml
    223200  OLD.xml and NEW.xml are XML-descriptors:
     
    244221
    245222GENERAL OPTIONS:
    246   -l|-lib|-library NAME
     223  -l|-library NAME
    247224      Library name (without version).
    248225
    249   -d1|-old|-o PATH
    250       Descriptor of 1st (old) library version.
     226  -old|-d1 PATH
     227      Descriptor of the 1st (old) library version.
    251228      It may be one of the following:
    252229     
    253          1. Java ARchive (*.jar)
     230         1. Java archive (*.jar)
    254231         2. XML-descriptor (VERSION.xml file):
    255232
     
    268245         3. API dump generated by -dump option
    269246
    270       If you are using 1, 4-6 descriptor types then you should
     247      If you are using *.jar as a descriptor then you should
    271248      specify version numbers with -v1 and -v2 options too.
    272 
    273       If you are using *.jar as a descriptor then the tool will try to
    274       get implementation version from MANIFEST.MF file.
    275 
    276   -d2|-new|-n PATH
    277       Descriptor of 2nd (new) library version.
     249      If version numbers are not specified then the tool will
     250      try to detect them automatically.
     251
     252  -new|-d2 PATH
     253      Descriptor of the 2nd (new) library version.
    278254
    279255EXTRA OPTIONS:
    280256  -client|-app PATH
    281       This option allows to specify the client Java ARchive that should be
     257      This option allows to specify the client Java archive that should be
    282258      checked for portability to the new library version.
    283      
     259
    284260  -binary|-bin
    285261      Show \"Binary\" compatibility problems only.
    286262      Generate report to \"bin_compat_report.html\".
    287      
     263
    288264  -source|-src
    289265      Show \"Source\" compatibility problems only.
    290266      Generate report to \"src_compat_report.html\".
    291      
     267
    292268  -v1|-version1 NUM
    293269      Specify 1st API version outside the descriptor. This option is needed
     
    323299      Dump library API to gzipped TXT format file. You can transfer it
    324300      anywhere and pass instead of the descriptor. Also it may be used
    325       for debugging the tool. Compatible dump versions: $API_DUMP_MAJOR.0<=V<=$API_DUMP_VERSION
     301      for debugging the tool.
    326302     
    327303  -classes-list PATH
     
    352328 
    353329  -dump-path PATH
    354       Specify a *.api.$AR_EXT or *.api file path where to generate an API dump.
     330      Specify a *.dump file path where to generate an API dump.
    355331      Default:
    356           abi_dumps/LIB_NAME/LIB_NAME_VERSION.api.$AR_EXT
     332          api_dumps/LIB_NAME/VERSION/API.dump
    357333
    358334  -report-path PATH
     
    455431    non-zero - Incompatible or the tool has run with errors.
    456432
    457 MORE INFORMATION:
    458     ".$HomePage{"Wiki"}."
    459     ".$HomePage{"Dev"}."\n\n";
    460 
    461 sub HELP_MESSAGE()
    462 { # -help
     433MORE INFO:
     434    ".$HomePage{"Doc"}."
     435    ".$HomePage{"Dev"};
     436
     437sub helpMsg() {
    463438    printMsg("INFO", $HelpMessage."\n");
    464439}
    465440
    466 my %TypeProblems_Kind=(
    467     "Binary"=>{
    468         "NonAbstract_Class_Added_Abstract_Method"=>"High",
    469         "Abstract_Class_Added_Abstract_Method"=>"Safe",
    470         "Abstract_Class_Added_Abstract_Method_Invoked_By_Others"=>"Medium",
    471         "Class_Removed_Abstract_Method"=>"High",
    472         "Interface_Added_Abstract_Method"=>"Safe",
    473         "Interface_Added_Abstract_Method_Invoked_By_Others"=>"Medium",
    474         "Interface_Removed_Abstract_Method"=>"High",
    475         "Removed_Class"=>"High",
    476         "Removed_Interface"=>"High",
    477         "Class_Method_Became_Abstract"=>"High",
    478         "Class_Method_Became_NonAbstract"=>"Low",
    479         "Interface_Method_Became_NonDefault"=>"High",
    480         "Interface_Method_Became_Default"=>"Safe",
    481         "Added_Super_Class"=>"Low",
    482         "Abstract_Class_Added_Super_Abstract_Class"=>"Safe",
    483         "Abstract_Class_Added_Super_Abstract_Class_Invoked_By_Others"=>"Medium",
    484         "Removed_Super_Class"=>"Medium",
    485         "Changed_Super_Class"=>"Medium",
    486         "Abstract_Class_Added_Super_Interface"=>"Safe",
    487         "Abstract_Class_Added_Super_Interface_Invoked_By_Others"=>"Medium",
    488         "Abstract_Class_Added_Super_Interface_With_Implemented_Methods"=>"Safe",
    489         "Class_Removed_Super_Interface"=>"High",
    490         "Interface_Added_Super_Interface"=>"Safe",
    491         "Interface_Added_Super_Interface_Used_By_Others"=>"Medium",
    492         "Interface_Added_Super_Constant_Interface"=>"Low",
    493         "Interface_Added_Super_Interface_With_Implemented_Methods"=>"Safe",
    494         "Interface_Removed_Super_Interface"=>"High",
    495         "Interface_Removed_Super_Constant_Interface"=>"Safe",
    496         "Class_Became_Interface"=>"High",
    497         "Interface_Became_Class"=>"High",
    498         "Class_Became_Final"=>"High",
    499         "Class_Became_Abstract"=>"High",
    500         "Class_Added_Field"=>"Safe",
    501         "Interface_Added_Field"=>"Safe",
    502         "Removed_NonConstant_Field"=>"High",
    503         "Removed_Constant_Field"=>"Low",
    504         "Renamed_Field"=>"High",
    505         "Renamed_Constant_Field"=>"Low",
    506         "Changed_Field_Type"=>"High",
    507         "Changed_Field_Access"=>"High",
    508         "Changed_Final_Field_Value"=>"Medium",
    509         "Changed_Final_Version_Field_Value"=>"Low",
    510         "Field_Became_Final"=>"Medium",
    511         "Field_Became_NonFinal"=>"Low",
    512         "NonConstant_Field_Became_Static"=>"High",
    513         "NonConstant_Field_Became_NonStatic"=>"High",
    514         "Class_Overridden_Method"=>"Low",
    515         "Class_Method_Moved_Up_Hierarchy"=>"Low"
    516     },
    517     "Source"=>{
    518         "NonAbstract_Class_Added_Abstract_Method"=>"High",
    519         "Abstract_Class_Added_Abstract_Method"=>"High",
    520         "Abstract_Class_Added_Abstract_Method_Invoked_By_Others"=>"High",
    521         "Interface_Added_Abstract_Method"=>"High",
    522         "Interface_Added_Abstract_Method_Invoked_By_Others"=>"High",
    523         "Class_Removed_Abstract_Method"=>"High",
    524         "Interface_Removed_Abstract_Method"=>"High",
    525         "Removed_Class"=>"High",
    526         "Removed_Interface"=>"High",
    527         "Class_Method_Became_Abstract"=>"High",
    528         "Class_Method_Became_NonAbstract"=>"Safe",
    529         "Interface_Method_Became_NonDefault"=>"High",
    530         "Interface_Method_Became_Default"=>"Safe",
    531         "Added_Super_Class"=>"Low",
    532         "Abstract_Class_Added_Super_Abstract_Class"=>"High",
    533         "Abstract_Class_Added_Super_Abstract_Class_Invoked_By_Others"=>"High",
    534         "Removed_Super_Class"=>"Medium",
    535         "Changed_Super_Class"=>"Medium",
    536         "Abstract_Class_Added_Super_Interface"=>"High",
    537         "Abstract_Class_Added_Super_Interface_Invoked_By_Others"=>"High",
    538         "Abstract_Class_Added_Super_Interface_With_Implemented_Methods"=>"Safe",
    539         "Class_Removed_Super_Interface"=>"High",
    540         "Interface_Added_Super_Interface"=>"High",
    541         "Interface_Added_Super_Interface_Used_By_Others"=>"High",
    542         "Interface_Added_Super_Constant_Interface"=>"Low",
    543         "Interface_Added_Super_Interface_With_Implemented_Methods"=>"Safe",
    544         "Interface_Removed_Super_Interface"=>"High",
    545         "Interface_Removed_Super_Constant_Interface"=>"High",
    546         "Class_Became_Interface"=>"High",
    547         "Interface_Became_Class"=>"High",
    548         "Class_Became_Final"=>"High",
    549         "Class_Became_Abstract"=>"High",
    550         "Class_Added_Field"=>"Safe",
    551         "Interface_Added_Field"=>"Safe",
    552         "Removed_NonConstant_Field"=>"High",
    553         "Removed_Constant_Field"=>"High",
    554         "Renamed_Field"=>"High",
    555         "Renamed_Constant_Field"=>"High",
    556         "Changed_Field_Type"=>"High",
    557         "Changed_Field_Access"=>"High",
    558         "Field_Became_Final"=>"Medium",
    559         "Constant_Field_Became_NonStatic"=>"High",
    560         "NonConstant_Field_Became_NonStatic"=>"High",
    561         "Removed_Annotation"=>"High"
    562     }
    563 );
    564 
    565 my %MethodProblems_Kind=(
    566     "Binary"=>{
    567         "Added_Method"=>"Safe",
    568         "Removed_Method"=>"High",
    569         "Method_Became_Static"=>"High",
    570         "Method_Became_NonStatic"=>"High",
    571         "NonStatic_Method_Became_Final"=>"Medium",
    572         "Changed_Method_Access"=>"High",
    573         "Method_Became_Synchronized"=>"Low",
    574         "Method_Became_NonSynchronized"=>"Low",
    575         "Method_Became_Abstract"=>"High",
    576         "Method_Became_NonAbstract"=>"Low",
    577         "Method_Became_NonDefault"=>"High",
    578         "Method_Became_Default"=>"Safe",
    579         "NonAbstract_Method_Added_Checked_Exception"=>"Low",
    580         "NonAbstract_Method_Removed_Checked_Exception"=>"Low",
    581         "Added_Unchecked_Exception"=>"Low",
    582         "Removed_Unchecked_Exception"=>"Low",
    583         "Variable_Arity_To_Array"=>"Low",# not implemented yet
    584         "Changed_Method_Return_From_Void"=>"High"
    585     },
    586     "Source"=>{
    587         "Added_Method"=>"Safe",
    588         "Removed_Method"=>"High",
    589         "Method_Became_Static"=>"Low",
    590         "Method_Became_NonStatic"=>"High",
    591         "Static_Method_Became_Final"=>"Medium",
    592         "NonStatic_Method_Became_Final"=>"Medium",
    593         "Changed_Method_Access"=>"High",
    594         "Method_Became_Abstract"=>"High",
    595         "Method_Became_NonAbstract"=>"Safe",
    596         "Method_Became_NonDefault"=>"High",
    597         "Method_Became_Default"=>"Safe",
    598         "Abstract_Method_Added_Checked_Exception"=>"Medium",
    599         "NonAbstract_Method_Added_Checked_Exception"=>"Medium",
    600         "Abstract_Method_Removed_Checked_Exception"=>"Medium",
    601         "NonAbstract_Method_Removed_Checked_Exception"=>"Medium"
    602     }
    603 );
    604 
     441#Aliases
     442my (%MethodInfo, %TypeInfo, %TName_Tid) = ();
     443
     444#Separate checked and unchecked exceptions
    605445my %KnownRuntimeExceptions= map {$_=>1} (
    606 # To separate checked- and unchecked- exceptions
    607446    "java.lang.AnnotationTypeMismatchException",
    608447    "java.lang.ArithmeticException",
     
    656495);
    657496
    658 my %Slash_Type=(
    659     "default"=>"/",
    660     "windows"=>"\\"
    661 );
    662 
    663 my $SLASH = $Slash_Type{$OSgroup}?$Slash_Type{$OSgroup}:$Slash_Type{"default"};
    664 
    665 my %OS_AddPath=(
    666 # this data needed if tool can't detect it automatically
    667 "macos"=>{
    668     "bin"=>{"/Developer/usr/bin"=>1}},
    669 "beos"=>{
    670     "bin"=>{"/boot/common/bin"=>1,"/boot/system/bin"=>1,"/boot/develop/abi"=>1}}
    671 );
    672 
    673 #Global variables
    674 my %RESULT;
    675 my $ExtractCounter = 0;
    676 my %Cache;
    677 my $TOP_REF = "<a class='top_ref' href='#Top'>to the top</a>";
    678 my %DEBUG_PATH;
    679 
    680 #Types
    681 my %TypeInfo;
    682 my $TYPE_ID = 0;
    683 my %CheckedTypes;
    684 my %TName_Tid;
    685 my %Class_Constructed;
    686 
    687 #Classes
    688 my %ClassList_User;
    689 my %UsedMethods_Client;
    690 my %UsedFields_Client;
    691 my %UsedClasses_Client;
    692 my %LibArchives;
    693 my %Class_Methods;
    694 my %Class_AbstractMethods;
    695 my %Class_Fields;
    696 my %MethodUsed;
    697 my %ClassMethod_AddedUsed;
    698 # my %FieldUsed;
    699 
    700497#java.lang.Object
    701498my %JavaObjectMethod = (
     
    714511);
    715512
    716 #Annotations
    717 my %AnnotationList_User;
    718 my %SkipAnnotationList_User;
     513#Global variables
     514my %Cache;
     515my %RESULT;
     516my $TOP_REF = "<a class='top_ref' href='#Top'>to the top</a>";
     517
     518#Types
     519my %CheckedTypes;
     520
     521#Classes
     522my %LibArchives;
     523my %Class_Methods;
     524my %Class_AbstractMethods;
     525my %Class_Fields;
     526my %ClassMethod_AddedUsed;
     527my %Class_Constructed;
    719528
    720529#Methods
    721530my %CheckedMethods;
    722 my %tr_name;
     531my %MethodUsed;
    723532
    724533#Merging
    725 my %MethodInfo;
    726 my $Version;
    727534my %AddedMethod_Abstract;
    728535my %RemovedMethod_Abstract;
    729536my %ChangedReturnFromVoid;
    730 my %SkipClasses;
    731 my %SkipPackages;
    732 my %KeepPackages;
    733 my %SkippedPackage;
     537my %CompatRules;
     538my %IncompleteRules;
    734539
    735540#Report
     
    737542
    738543#Recursion locks
    739 my @RecurSymlink;
    740544my @RecurTypes;
    741 
    742 #System
    743 my %SystemPaths;
    744 my %DefaultBinPaths;
    745545
    746546#Problem descriptions
     
    760560my $Content_Counter = 0;
    761561
    762 #Modes
    763 my $JoinReport = 1;
    764 my $DoubleReport = 0;
    765 
    766 sub get_CmdPath($)
     562sub getModules()
     563{
     564    my $TOOL_DIR = dirname($0);
     565    if(not $TOOL_DIR)
     566    { # patch for MS Windows
     567        $TOOL_DIR = ".";
     568    }
     569    my @SEARCH_DIRS = (
     570        # tool's directory
     571        abs_path($TOOL_DIR),
     572        # relative path to modules
     573        abs_path($TOOL_DIR)."/../share/japi-compliance-checker",
     574        # install path
     575        'MODULES_INSTALL_PATH'
     576    );
     577    foreach my $DIR (@SEARCH_DIRS)
     578    {
     579        if($DIR!~/\A(\/|\w+:[\/\\])/)
     580        { # relative path
     581            $DIR = abs_path($TOOL_DIR)."/".$DIR;
     582        }
     583        if(-d $DIR."/modules") {
     584            return $DIR."/modules";
     585        }
     586    }
     587   
     588    print STDERR "ERROR: can't find modules (Did you installed the tool by 'make install' command?)\n";
     589    exit(9); # Module_Error
     590}
     591
     592sub loadModule($)
    767593{
    768594    my $Name = $_[0];
    769     return "" if(not $Name);
    770     if(defined $Cache{"get_CmdPath"}{$Name}) {
    771         return $Cache{"get_CmdPath"}{$Name};
    772     }
    773     my $Path = search_Cmd($Name);
    774     if(not $Path and $OSgroup eq "windows")
    775     { # search for *.exe file
    776         $Path=search_Cmd($Name.".exe");
    777     }
    778     if (not $Path) {
    779         $Path=search_Cmd_Path($Name);
    780     }
    781     if($Path=~/\s/) {
    782         $Path = "\"".$Path."\"";
    783     }
    784     return ($Cache{"get_CmdPath"}{$Name} = $Path);
    785 }
    786 
    787 sub search_Cmd($)
    788 {
    789     my $Name = $_[0];
    790     return "" if(not $Name);
    791     if(defined $Cache{"search_Cmd"}{$Name}) {
    792         return $Cache{"search_Cmd"}{$Name};
    793     }
    794     if(defined $JdkPath)
    795     {
    796         if(-x $JdkPath."/".$Name) {
    797             return ($Cache{"search_Cmd"}{$Name} = $JdkPath."/".$Name);
    798         }
    799        
    800         if(-x $JdkPath."/bin/".$Name) {
    801             return ($Cache{"search_Cmd"}{$Name} = $JdkPath."/bin/".$Name);
    802         }
    803     }
    804     if(my $DefaultPath = get_CmdPath_Default($Name)) {
    805         return ($Cache{"search_Cmd"}{$Name} = $DefaultPath);
    806     }
    807     return ($Cache{"search_Cmd"}{$Name} = "");
    808 }
    809 
    810 sub search_Cmd_Path($)
    811 {
    812     my $Name = $_[0];
    813     return "" if(not $Name);
    814    
    815     if(defined $Cache{"search_Cmd_Path"}{$Name}) {
    816         return $Cache{"search_Cmd_Path"}{$Name};
    817     }
    818    
    819     if(defined $SystemPaths{"bin"})
    820     {
    821         foreach my $Path (sort {length($a)<=>length($b)} keys(%{$SystemPaths{"bin"}}))
    822         {
    823             if(-f $Path."/".$Name or -f $Path."/".$Name.".exe") {
    824                 return ($Cache{"search_Cmd_Path"}{$Name} = joinPath($Path,$Name));
    825             }
    826         }
    827     }
    828 
    829     return ($Cache{"search_Cmd_Path"}{$Name} = "");
    830 }
    831 
    832 sub get_CmdPath_Default($)
    833 { # search in PATH
    834     return "" if(not $_[0]);
    835     if(defined $Cache{"get_CmdPath_Default"}{$_[0]}) {
    836         return $Cache{"get_CmdPath_Default"}{$_[0]};
    837     }
    838     return ($Cache{"get_CmdPath_Default"}{$_[0]} = get_CmdPath_Default_I($_[0]));
    839 }
    840 
    841 sub get_CmdPath_Default_I($)
    842 { # search in PATH
    843     my $Name = $_[0];
    844     if($Name=~/find/)
    845     { # special case: search for "find" utility
    846         if(`find \"$TMP_DIR\" -maxdepth 0 2>\"$TMP_DIR/null\"`) {
    847             return "find";
    848         }
    849     }
    850     if(get_version($Name)) {
    851         return $Name;
    852     }
    853     if($OSgroup eq "windows")
    854     {
    855         if(`$Name /? 2>\"$TMP_DIR/null\"`) {
    856             return $Name;
    857         }
    858     }
    859     if($Name!~/which/)
    860     {
    861         if(my $WhichCmd = get_CmdPath("which"))
    862         {
    863             if(`$WhichCmd $Name 2>\"$TMP_DIR/null\"`) {
    864                 return $Name;
    865             }
    866         }
    867     }
    868     foreach my $Path (sort {length($a)<=>length($b)} keys(%DefaultBinPaths))
    869     {
    870         if(-f $Path."/".$Name) {
    871             return joinPath($Path,$Name);
    872         }
    873     }
    874     return "";
    875 }
    876 
    877 sub showPos($)
    878 {
    879     my $Number = $_[0];
    880     if(not $Number) {
    881         $Number = 1;
    882     }
    883     else {
    884         $Number = int($Number)+1;
    885     }
    886     if($Number>3) {
    887         return $Number."th";
    888     }
    889     elsif($Number==1) {
    890         return "1st";
    891     }
    892     elsif($Number==2) {
    893         return "2nd";
    894     }
    895     elsif($Number==3) {
    896         return "3rd";
    897     }
    898     else {
    899         return $Number;
    900     }
    901 }
    902 
    903 sub getAR_EXT($)
    904 {
    905     my $Target = $_[0];
    906     if(my $Ext = $OS_Archive{$Target}) {
    907         return $Ext;
    908     }
    909     return $OS_Archive{"default"};
    910 }
    911 
    912 sub readDescriptor($$)
    913 {
    914     my ($LibVersion, $Content) = @_;
    915     return if(not $LibVersion);
    916     my $DName = $DumpAPI?"descriptor":"descriptor \"d$LibVersion\"";
    917     if(not $Content) {
    918         exitStatus("Error", "$DName is empty");
    919     }
    920     if($Content!~/\</) {
    921         exitStatus("Error", "descriptor should be one of the following:\n  Java ARchive, XML descriptor, gzipped API dump or directory with Java ARchives.");
    922     }
    923     $Content=~s/\/\*(.|\n)+?\*\///g;
    924     $Content=~s/<\!--(.|\n)+?-->//g;
    925     $Descriptor{$LibVersion}{"Version"} = parseTag(\$Content, "version");
    926     $Descriptor{$LibVersion}{"Version"} = $TargetVersion{$LibVersion} if($TargetVersion{$LibVersion});
    927     if($Descriptor{$LibVersion}{"Version"} eq "") {
    928         exitStatus("Error", "version in the $DName is not specified (<version> section)");
    929     }
    930    
    931     my $DArchives = parseTag(\$Content, "archives");
    932     if(not $DArchives){
    933         exitStatus("Error", "Java ARchives in the $DName are not specified (<archive> section)");
    934     }
    935     else
    936     {# append the descriptor Java ARchives list
    937         if($Descriptor{$LibVersion}{"Archives"}) {
    938             $Descriptor{$LibVersion}{"Archives"} .= "\n".$DArchives;
    939         }
    940         else {
    941             $Descriptor{$LibVersion}{"Archives"} = $DArchives;
    942         }
    943         foreach my $Path (split(/\s*\n\s*/, $DArchives))
    944         {
    945             if(not -e $Path) {
    946                 exitStatus("Access_Error", "can't access \'$Path\'");
    947             }
    948         }
    949     }
    950     foreach my $Package (split(/\s*\n\s*/, parseTag(\$Content, "skip_packages"))) {
    951         $SkipPackages{$LibVersion}{$Package} = 1;
    952     }
    953     foreach my $Package (split(/\s*\n\s*/, parseTag(\$Content, "packages"))) {
    954         $KeepPackages{$LibVersion}{$Package} = 1;
    955     }
    956 }
    957 
    958 sub parseTag($$)
    959 {
    960     my ($CodeRef, $Tag) = @_;
    961     return "" if(not $CodeRef or not ${$CodeRef} or not $Tag);
    962     if(${$CodeRef}=~s/\<\Q$Tag\E\>((.|\n)+?)\<\/\Q$Tag\E\>//)
    963     {
    964         my $Content = $1;
    965         $Content=~s/(\A\s+|\s+\Z)//g;
    966         return $Content;
    967     }
    968     else {
    969         return "";
    970     }
    971 }
    972 
    973 sub ignore_path($$)
    974 {
    975     my ($Path, $Prefix) = @_;
    976     return 1 if(not $Path or not -e $Path
    977     or not $Prefix or not -e $Prefix);
    978     return 1 if($Path=~/\~\Z/);# skipping system backup files
    979     # skipping hidden .svn, .git, .bzr, .hg and CVS directories
    980     return 1 if(cut_path_prefix($Path, $Prefix)=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/);
    981     return 0;
    982 }
    983 
    984 sub cut_path_prefix($$)
    985 {
    986     my ($Path, $Prefix) = @_;
    987     $Prefix=~s/[\/\\]+\Z//;
    988     $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
    989     return $Path;
    990 }
    991 
    992 sub get_filename($)
    993 { # much faster than basename() from File::Basename module
    994     if(defined $Cache{"get_filename"}{$_[0]}) {
    995         return $Cache{"get_filename"}{$_[0]};
    996     }
    997     if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
    998         return ($Cache{"get_filename"}{$_[0]}=$1);
    999     }
    1000     return ($Cache{"get_filename"}{$_[0]}="");
    1001 }
    1002 
    1003 sub get_dirname($)
    1004 { # much faster than dirname() from File::Basename module
    1005     if(defined $Cache{"get_dirname"}{$_[0]}) {
    1006         return $Cache{"get_dirname"}{$_[0]};
    1007     }
    1008     if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
    1009         return ($Cache{"get_dirname"}{$_[0]}=$1);
    1010     }
    1011     return ($Cache{"get_dirname"}{$_[0]}="");
    1012 }
    1013 
    1014 sub separate_path($) {
    1015     return (get_dirname($_[0]), get_filename($_[0]));
    1016 }
    1017 
    1018 sub joinPath($$)
    1019 {
    1020     return join($SLASH, @_);
    1021 }
    1022 
    1023 sub get_abs_path($)
    1024 { # abs_path() should NOT be called for absolute inputs
    1025   # because it can change them
    1026     my $Path = $_[0];
    1027     if(not is_abs($Path)) {
    1028         $Path = abs_path($Path);
    1029     }
    1030     return $Path;
    1031 }
    1032 
    1033 sub is_abs($) {
    1034     return ($_[0]=~/\A(\/|\w+:[\/\\])/);
    1035 }
    1036 
    1037 sub cmd_find($$$$)
    1038 {
    1039     my ($Path, $Type, $Name, $MaxDepth) = @_;
    1040     return () if(not $Path or not -e $Path);
    1041     if($OSgroup eq "windows")
    1042     {
    1043         my $DirCmd = get_CmdPath("dir");
    1044         if(not $DirCmd) {
    1045             exitStatus("Not_Found", "can't find \"dir\" command");
    1046         }
    1047         $Path=~s/[\\]+\Z//;
    1048         $Path = get_abs_path($Path);
    1049         my $Cmd = $DirCmd." \"$Path\" /B /O";
    1050         if($MaxDepth!=1) {
    1051             $Cmd .= " /S";
    1052         }
    1053         if($Type eq "d") {
    1054             $Cmd .= " /AD";
    1055         }
    1056         my @Files = ();
    1057         if($Name)
    1058         { # FIXME: how to search file names in MS shell?
    1059             $Name=~s/\*/.*/g if($Name!~/\]/);
    1060             foreach my $File (split(/\n/, `$Cmd`))
    1061             {
    1062                 if($File=~/$Name\Z/i) {
    1063                     push(@Files, $File);   
    1064                 }
    1065             }
    1066         }
    1067         else {
    1068             @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
    1069         }
    1070         my @AbsPaths = ();
    1071         foreach my $File (@Files)
    1072         {
    1073             if(not is_abs($File)) {
    1074                 $File = joinPath($Path, $File);
    1075             }
    1076             if($Type eq "f" and not -f $File)
    1077             { # skip dirs
    1078                 next;
    1079             }
    1080             push(@AbsPaths, $File);
    1081         }
    1082         if($Type eq "d") {
    1083             push(@AbsPaths, $Path);
    1084         }
    1085         return @AbsPaths;
    1086     }
    1087     else
    1088     {
    1089         my $FindCmd = get_CmdPath("find");
    1090         if(not $FindCmd) {
    1091             exitStatus("Not_Found", "can't find a \"find\" command");
    1092         }
    1093         $Path = get_abs_path($Path);
    1094         if(-d $Path and -l $Path
    1095         and $Path!~/\/\Z/)
    1096         { # for directories that are symlinks
    1097             $Path.="/";
    1098         }
    1099         my $Cmd = $FindCmd." \"$Path\"";
    1100         if($MaxDepth) {
    1101             $Cmd .= " -maxdepth $MaxDepth";
    1102         }
    1103         if($Type) {
    1104             $Cmd .= " -type $Type";
    1105         }
    1106         if($Name)
    1107         {
    1108             if($Name=~/\]/) {
    1109                 $Cmd .= " -regex \"$Name\"";
    1110             }
    1111             else {
    1112                 $Cmd .= " -name \"$Name\"";
    1113             }
    1114         }
    1115         return split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
    1116     }
    1117 }
    1118 
    1119 sub path_format($$)
    1120 { # forward slash to pass into MinGW GCC
    1121     my ($Path, $Fmt) = @_;
    1122     if($Fmt eq "windows")
    1123     {
    1124         $Path=~s/\//\\/g;
    1125         $Path=lc($Path);
    1126     }
    1127     else {
    1128         $Path=~s/\\/\//g;
    1129     }
    1130     return $Path;
    1131 }
    1132 
    1133 sub unpackDump($)
    1134 {
    1135     my $Path = $_[0];
    1136     return "" if(not $Path or not -e $Path);
    1137    
    1138     if(isDumpFile($Path)) {
    1139         return $Path;
    1140     }
    1141    
    1142     $Path = get_abs_path($Path);
    1143     $Path = path_format($Path, $OSgroup);
    1144     my ($Dir, $FileName) = separate_path($Path);
    1145     my $UnpackDir = $TMP_DIR."/unpack";
    1146     if(-d $UnpackDir) {
    1147         rmtree($UnpackDir);
    1148     }
    1149     mkpath($UnpackDir);
    1150     if($FileName=~s/\Q.zip\E\Z//g)
    1151     { # *.zip
    1152         my $UnzipCmd = get_CmdPath("unzip");
    1153         if(not $UnzipCmd) {
    1154             exitStatus("Not_Found", "can't find \"unzip\" command");
    1155         }
    1156         chdir($UnpackDir);
    1157         system("$UnzipCmd \"$Path\" >contents.txt");
    1158         if($?) {
    1159             exitStatus("Error", "can't extract \'$Path\'");
    1160         }
    1161         chdir($ORIG_DIR);
    1162         my @Contents = ();
    1163         foreach (split("\n", readFile("$UnpackDir/contents.txt")))
    1164         {
    1165             if(/inflating:\s*([^\s]+)/) {
    1166                 push(@Contents, $1);
    1167             }
    1168         }
    1169         if(not @Contents) {
    1170             exitStatus("Error", "can't extract \'$Path\'");
    1171         }
    1172         return joinPath($UnpackDir, $Contents[0]);
    1173     }
    1174     elsif($FileName=~s/\Q.tar.gz\E\Z//g)
    1175     { # *.tar.gz
    1176         if($OSgroup eq "windows")
    1177         { # -xvzf option is not implemented in tar.exe (2003)
    1178           # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
    1179             my $TarCmd = get_CmdPath("tar");
    1180             if(not $TarCmd) {
    1181                 exitStatus("Not_Found", "can't find \"tar\" command");
    1182             }
    1183             my $GzipCmd = get_CmdPath("gzip");
    1184             if(not $GzipCmd) {
    1185                 exitStatus("Not_Found", "can't find \"gzip\" command");
    1186             }
    1187             chdir($UnpackDir);
    1188             qx/$GzipCmd -k -d -f "$Path"/; # keep input files (-k)
    1189             if($?) {
    1190                 exitStatus("Error", "can't extract \'$Path\'");
    1191             }
    1192             my @Contents = qx/$TarCmd -xvf "$Dir\\$FileName.tar"/;
    1193             if($? or not @Contents) {
    1194                 exitStatus("Error", "can't extract \'$Path\'");
    1195             }
    1196             chdir($ORIG_DIR);
    1197             unlink($Dir."/".$FileName.".tar");
    1198             chomp $Contents[0];
    1199             return joinPath($UnpackDir, $Contents[0]);
    1200         }
    1201         else
    1202         { # Linux, Unix, OS X
    1203             my $TarCmd = get_CmdPath("tar");
    1204             if(not $TarCmd) {
    1205                 exitStatus("Not_Found", "can't find \"tar\" command");
    1206             }
    1207             chdir($UnpackDir);
    1208             my @Contents = qx/$TarCmd -xvzf "$Path" 2>&1/;
    1209             if($? or not @Contents) {
    1210                 exitStatus("Error", "can't extract \'$Path\'");
    1211             }
    1212             chdir($ORIG_DIR);
    1213             $Contents[0]=~s/^x //; # OS X
    1214             chomp $Contents[0];
    1215             return joinPath($UnpackDir, $Contents[0]);
    1216         }
    1217     }
     595    if(defined $LoadedModules{$Name}) {
     596        return;
     597    }
     598    my $Path = $MODULES_DIR."/Internals/$Name.pm";
     599    if(not -f $Path)
     600    {
     601        print STDERR "can't access \'$Path\'\n";
     602        exit(2);
     603    }
     604    require $Path;
     605    $LoadedModules{$Name} = 1;
     606}
     607
     608sub readModule($$)
     609{
     610    my ($Module, $Name) = @_;
     611    my $Path = $MODULES_DIR."/Internals/$Module/".$Name;
     612    if(not -f $Path) {
     613        exitStatus("Module_Error", "can't access \'$Path\'");
     614    }
     615    return readFile($Path);
    1218616}
    1219617
     
    1225623    {
    1226624        next if(not $ClassName);
    1227         my $Type1_Id = $TName_Tid{1}{$ClassName};
    1228         my %Type1 = get_Type($Type1_Id, 1);
    1229        
    1230         if($Type1{"Type"}!~/class|interface/) {
     625        my $Type1 = getType($TName_Tid{1}{$ClassName}, 1);
     626       
     627        if($Type1->{"Type"}!~/class|interface/) {
    1231628            next;
    1232629        }
    1233630       
    1234         if(defined $Type1{"Access"}
    1235         and $Type1{"Access"}=~/private/) {
     631        if(defined $Type1->{"Access"}
     632        and $Type1->{"Access"}=~/private/) {
    1236633            next;
    1237634        }
    1238635       
    1239         if(not classFilter(\%Type1, 1, 0)) {
     636        if(not classFilter($Type1, 1, 0)) {
    1240637            next;
    1241638        }
     
    1253650                $CheckedMethods{$Method} = 1;
    1254651               
    1255                 if($Type1{"Type"} eq "class")
     652                if($Type1->{"Type"} eq "class")
    1256653                {
    1257654                    %{$CompatProblems{$Method}{"Removed_Class"}{"this"}} = (
    1258655                        "Type_Name"=>$ClassName,
    1259                         "Target"=>$ClassName  );
     656                        "Target"=>$ClassName);
    1260657                }
    1261658                else
     
    1263660                    %{$CompatProblems{$Method}{"Removed_Interface"}{"this"}} = (
    1264661                        "Type_Name"=>$ClassName,
    1265                         "Target"=>$ClassName  );
     662                        "Target"=>$ClassName);
    1266663                }
    1267664               
     
    1273670    foreach my $Class_Id (keys(%{$TypeInfo{1}}))
    1274671    {
    1275         my %Class1 = get_Type($Class_Id, 1);
    1276        
    1277         if($Class1{"Type"}!~/class|interface/) {
     672        my $Class1 = getType($Class_Id, 1);
     673       
     674        if($Class1->{"Type"}!~/class|interface/) {
    1278675            next;
    1279676        }
    1280677       
    1281         if(defined $Class1{"Access"}
    1282         and $Class1{"Access"}=~/private/) {
     678        if(defined $Class1->{"Access"}
     679        and $Class1->{"Access"}=~/private/) {
    1283680            next;
    1284681        }
    1285682       
    1286         if(not classFilter(\%Class1, 1, 1)) {
     683        if(not classFilter($Class1, 1, 1)) {
    1287684            next;
    1288685        }
    1289686       
    1290         my $ClassName = $Class1{"Name"};
     687        my $ClassName = $Class1->{"Name"};
    1291688       
    1292689        if(my $Class2_Id = $TName_Tid{2}{$ClassName})
     
    1294691            if(not defined $Class_Methods{1}{$ClassName})
    1295692            {
    1296                 my %Class2 = get_Type($Class2_Id, 2);
     693                my $Class2 = getType($Class2_Id, 2);
    1297694               
    1298                 foreach my $Field (keys(%{$Class1{"Fields"}}))
     695                foreach my $Field (keys(%{$Class1->{"Fields"}}))
    1299696                {
    1300                     my $FieldInfo = $Class1{"Fields"}{$Field};
     697                    my $FieldInfo = $Class1->{"Fields"}{$Field};
    1301698                   
    1302699                    my $FAccess = $FieldInfo->{"Access"};
     
    1309706                        $CheckedTypes{$ClassName} = 1;
    1310707                       
    1311                         if(not defined $Class2{"Fields"}{$Field})
     708                        if(not defined $Class2->{"Fields"}{$Field})
    1312709                        {
    1313710                            %{$CompatProblems{".client_method"}{"Removed_NonConstant_Field"}{$Field}}=(
    1314711                                "Target"=>$Field,
    1315712                                "Type_Name"=>$ClassName,
    1316                                 "Type_Type"=>$Class1{"Type"},
    1317                                 "Field_Type"=>get_TypeName($FieldInfo->{"Type"}, 1)  );
     713                                "Type_Type"=>$Class1->{"Type"},
     714                                "Field_Type"=>getTypeName($FieldInfo->{"Type"}, 1));
    1318715                        }
    1319716                    }
     
    1323720        else
    1324721        { # removed
    1325             if(defined $Class1{"Annotation"})
     722            if(defined $Class1->{"Annotation"})
    1326723            {
    1327724                %{$CompatProblems{".client_method"}{"Removed_Annotation"}{"this"}} = (
    1328725                    "Type_Name"=>$ClassName,
    1329                     "Target"=>$ClassName  );
     726                    "Target"=>$ClassName);
    1330727            }
    1331728           
     
    1335732                if(not defined $ReportedRemoved{$ClassName})
    1336733                {
    1337                     foreach my $Field (keys(%{$Class1{"Fields"}}))
     734                    foreach my $Field (keys(%{$Class1->{"Fields"}}))
    1338735                    {
    1339                         my $FieldInfo = $Class1{"Fields"}{$Field};
     736                        my $FieldInfo = $Class1->{"Fields"}{$Field};
    1340737                       
    1341738                        my $FAccess = $FieldInfo->{"Access"};
     
    1348745                            $CheckedTypes{$ClassName} = 1;
    1349746                           
    1350                             if($Class1{"Type"} eq "class")
     747                            if($Class1->{"Type"} eq "class")
    1351748                            {
    1352749                                %{$CompatProblems{".client_method"}{"Removed_Class"}{"this"}} = (
    1353750                                    "Type_Name"=>$ClassName,
    1354                                     "Target"=>$ClassName  );
     751                                    "Target"=>$ClassName);
    1355752                            }
    1356753                            else
     
    1358755                                %{$CompatProblems{".client_method"}{"Removed_Interface"}{"this"}} = (
    1359756                                    "Type_Name"=>$ClassName,
    1360                                     "Target"=>$ClassName  );
     757                                    "Target"=>$ClassName);
    1361758                            }
    1362759                        }
     
    1405802sub pushType($$)
    1406803{
    1407     my %TypeDescriptor=(
     804    my %TypeDescriptor = (
    1408805        "Tid1"  => $_[0],
    1409         "Tid2"  => $_[1]  );
     806        "Tid2"  => $_[1]);
    1410807    push(@RecurTypes, \%TypeDescriptor);
    1411808}
    1412809
    1413 sub get_SFormat($)
     810sub getSFormat($)
    1414811{
    1415812    my $Name = $_[0];
     
    1418815}
    1419816
    1420 sub get_PFormat($)
    1421 {
    1422     my $Name = $_[0];
    1423     $Name=~s/\//./g;
    1424     return $Name;
    1425 }
    1426 
    1427 sub get_ConstantValue($$)
     817sub getConstantValue($$)
    1428818{
    1429819    my ($Value, $ValueType) = @_;
    1430     return "" if(not $Value);
     820   
     821    if(not defined $Value) {
     822        return undef;
     823    }
     824   
    1431825    if($Value eq "\@EMPTY_STRING\@") {
    1432826        return "\"\"";
     
    1435829        return "\"".$Value."\"";
    1436830    }
    1437     else {
    1438         return $Value;
    1439     }
     831   
     832    return $Value;
    1440833}
    1441834
     
    1466859    }
    1467860   
    1468     my %Type1 = get_Type($Type1_Id, 1);
    1469     my %Type2 = get_Type($Type2_Id, 2);
    1470861    if(isRecurType($Type1_Id, $Type2_Id))
    1471862    { # do not follow to recursive declarations
    1472863        return {};
    1473864    }
     865   
     866    my %Type1 = %{getType($Type1_Id, 1)};
     867    my %Type2 = %{getType($Type2_Id, 2)};
     868   
    1474869    return {} if(not $Type1{"Name"} or not $Type2{"Name"});
    1475870    return {} if(not $Type1{"Archive"} or not $Type2{"Archive"});
     
    1502897    {
    1503898        %{$SubProblems{"Class_Became_Interface"}{""}}=(
    1504             "Type_Name"=>$Type1{"Name"}  );
     899            "Type_Name"=>$Type1{"Name"});
    1505900       
    1506901        return ($Cache{"mergeTypes"}{$Type1_Id}{$Type2_Id} = \%SubProblems);
     
    1510905    {
    1511906        %{$SubProblems{"Interface_Became_Class"}{""}}=(
    1512             "Type_Name"=>$Type1{"Name"}  );
     907            "Type_Name"=>$Type1{"Name"});
    1513908       
    1514909        return ($Cache{"mergeTypes"}{$Type1_Id}{$Type2_Id} = \%SubProblems);
     
    1519914        %{$SubProblems{"Class_Became_Final"}{""}}=(
    1520915            "Type_Name"=>$Type1{"Name"},
    1521             "Target"=>$Type1{"Name"}  );
     916            "Target"=>$Type1{"Name"});
    1522917    }
    1523918    if(not $Type1{"Abstract"}
     
    1525920    {
    1526921        %{$SubProblems{"Class_Became_Abstract"}{""}}=(
    1527             "Type_Name"=>$Type1{"Name"}  );
     922            "Type_Name"=>$Type1{"Name"});
    1528923    }
    1529924   
     
    1538933                if(my @InvokedBy = sort keys(%{$MethodUsed{2}{$AddedMethod}}))
    1539934                {
    1540                     %{$SubProblems{"Abstract_Class_Added_Abstract_Method_Invoked_By_Others"}{get_SFormat($AddedMethod)}} = (
     935                    %{$SubProblems{"Abstract_Class_Added_Abstract_Method_Invoked_By_Others"}{getSFormat($AddedMethod)}} = (
    1541936                        "Type_Name"=>$Type1{"Name"},
    1542937                        "Type_Type"=>$Type1{"Type"},
    1543938                        "Target"=>$AddedMethod,
    1544                         "InvokedBy"=>$InvokedBy[0]  );
     939                        "Invoked_By"=>$InvokedBy[0]);
    1545940                }
    1546941                else
    1547942                {
    1548                     %{$SubProblems{"Abstract_Class_Added_Abstract_Method"}{get_SFormat($AddedMethod)}} = (
     943                    %{$SubProblems{"Abstract_Class_Added_Abstract_Method"}{getSFormat($AddedMethod)}} = (
    1549944                        "Type_Name"=>$Type1{"Name"},
    1550945                        "Type_Type"=>$Type1{"Type"},
    1551                         "Target"=>$AddedMethod  );
     946                        "Target"=>$AddedMethod);
    1552947                }
    1553948            }
    1554949            else
    1555950            {
    1556                 %{$SubProblems{"NonAbstract_Class_Added_Abstract_Method"}{get_SFormat($AddedMethod)}} = (
     951                %{$SubProblems{"NonAbstract_Class_Added_Abstract_Method"}{getSFormat($AddedMethod)}} = (
    1557952                    "Type_Name"=>$Type1{"Name"},
    1558953                    "Type_Type"=>$Type1{"Type"},
    1559                     "Target"=>$AddedMethod  );
     954                    "Target"=>$AddedMethod);
    1560955            }
    1561956        }
     
    1564959            if(my @InvokedBy = sort keys(%{$MethodUsed{2}{$AddedMethod}}))
    1565960            {
    1566                 %{$SubProblems{"Interface_Added_Abstract_Method_Invoked_By_Others"}{get_SFormat($AddedMethod)}} = (
     961                %{$SubProblems{"Interface_Added_Abstract_Method_Invoked_By_Others"}{getSFormat($AddedMethod)}} = (
    1567962                    "Type_Name"=>$Type1{"Name"},
    1568963                    "Type_Type"=>$Type1{"Type"},
    1569964                    "Target"=>$AddedMethod,
    1570                     "InvokedBy"=>$InvokedBy[0]  );
     965                    "Invoked_By"=>$InvokedBy[0]);
    1571966            }
    1572967            else
    1573968            {
    1574                 %{$SubProblems{"Interface_Added_Abstract_Method"}{get_SFormat($AddedMethod)}} = (
     969                %{$SubProblems{"Interface_Added_Abstract_Method"}{getSFormat($AddedMethod)}} = (
    1575970                    "Type_Name"=>$Type1{"Name"},
    1576971                    "Type_Type"=>$Type1{"Type"},
    1577                     "Target"=>$AddedMethod  );
     972                    "Target"=>$AddedMethod);
    1578973            }
    1579974        }
     
    1583978        if($Type1{"Type"} eq "class")
    1584979        {
    1585             %{$SubProblems{"Class_Removed_Abstract_Method"}{get_SFormat($RemovedMethod)}} = (
     980            %{$SubProblems{"Class_Removed_Abstract_Method"}{getSFormat($RemovedMethod)}} = (
    1586981                "Type_Name"=>$Type1{"Name"},
    1587982                "Type_Type"=>$Type1{"Type"},
    1588                 "Target"=>$RemovedMethod  );
     983                "Target"=>$RemovedMethod);
    1589984        }
    1590985        else
    1591986        {
    1592             %{$SubProblems{"Interface_Removed_Abstract_Method"}{get_SFormat($RemovedMethod)}} = (
     987            %{$SubProblems{"Interface_Removed_Abstract_Method"}{getSFormat($RemovedMethod)}} = (
    1593988                "Type_Name"=>$Type1{"Name"},
    1594989                "Type_Type"=>$Type1{"Type"},
    1595                 "Target"=>$RemovedMethod  );
     990                "Target"=>$RemovedMethod);
    1596991        }
    1597992    }
     
    1599994    and $Type2{"Type"} eq "class")
    1600995    {
    1601         my %SuperClass1 = get_Type($Type1{"SuperClass"}, 1);
    1602         my %SuperClass2 = get_Type($Type2{"SuperClass"}, 2);
    1603         if($SuperClass2{"Name"} ne $SuperClass1{"Name"})
    1604         {
    1605             if($SuperClass1{"Name"} eq "java.lang.Object"
    1606             or not $SuperClass1{"Name"})
     996        my $SuperClass1 = getType($Type1{"SuperClass"}, 1);
     997        my $SuperClass2 = getType($Type2{"SuperClass"}, 2);
     998       
     999        my $SuperClassName1 = $SuperClass1->{"Name"};
     1000        my $SuperClassName2 = $SuperClass2->{"Name"};
     1001       
     1002        if($SuperClassName2 ne $SuperClassName1)
     1003        {
     1004            if($SuperClassName1 eq "java.lang.Object"
     1005            or not $SuperClassName1)
    16071006            {
    16081007              # Java 6: java.lang.Object
    16091008              # Java 7: none
    1610                 if($SuperClass2{"Name"} ne "java.lang.Object")
     1009                if($SuperClassName2 ne "java.lang.Object")
    16111010                {
    1612                     if($SuperClass2{"Abstract"}
     1011                    if($SuperClass2->{"Abstract"}
    16131012                    and $Type1{"Abstract"} and $Type2{"Abstract"}
    1614                     and keys(%{$Class_AbstractMethods{2}{$SuperClass2{"Name"}}}))
     1013                    and keys(%{$Class_AbstractMethods{2}{$SuperClassName2}}))
    16151014                    {
    16161015                        if(my ($Invoked, $InvokedBy) = getInvoked($Type1{"Name"}))
     
    16181017                            %{$SubProblems{"Abstract_Class_Added_Super_Abstract_Class_Invoked_By_Others"}{""}} = (
    16191018                                "Type_Name"=>$Type1{"Name"},
    1620                                 "Target"=>$SuperClass2{"Name"},
     1019                                "Target"=>$SuperClassName2,
    16211020                                "Invoked"=>$Invoked,
    1622                                 "InvokedBy"=>$InvokedBy  );
     1021                                "Invoked_By"=>$InvokedBy);
    16231022                        }
    16241023                        else
     
    16261025                            %{$SubProblems{"Abstract_Class_Added_Super_Abstract_Class"}{""}} = (
    16271026                                "Type_Name"=>$Type1{"Name"},
    1628                                 "Target"=>$SuperClass2{"Name"}  );
     1027                                "Target"=>$SuperClassName2);
    16291028                        }
    16301029                    }
     
    16331032                        %{$SubProblems{"Added_Super_Class"}{""}} = (
    16341033                            "Type_Name"=>$Type1{"Name"},
    1635                             "Target"=>$SuperClass2{"Name"}  );
    1636                     }
    1637                 }
    1638             }
    1639             elsif($SuperClass2{"Name"} eq "java.lang.Object"
    1640             or not $SuperClass2{"Name"})
     1034                            "Target"=>$SuperClassName2);
     1035                    }
     1036                }
     1037            }
     1038            elsif($SuperClassName2 eq "java.lang.Object"
     1039            or not $SuperClassName2)
    16411040            {
    16421041              # Java 6: java.lang.Object
    16431042              # Java 7: none
    1644                 if($SuperClass1{"Name"} ne "java.lang.Object")
     1043                if($SuperClassName1 ne "java.lang.Object")
    16451044                {
    16461045                    %{$SubProblems{"Removed_Super_Class"}{""}} = (
    16471046                        "Type_Name"=>$Type1{"Name"},
    1648                         "Target"=>$SuperClass1{"Name"}  );
     1047                        "Target"=>$SuperClassName1);
    16491048                }
    16501049            }
     
    16531052                %{$SubProblems{"Changed_Super_Class"}{""}} = (
    16541053                    "Type_Name"=>$Type1{"Name"},
    1655                     "Target"=>$SuperClass1{"Name"},
    1656                     "Old_Value"=>$SuperClass1{"Name"},
    1657                     "New_Value"=>$SuperClass2{"Name"}  );
    1658             }
    1659         }
    1660     }
    1661     my %SuperInterfaces_Old = map {get_TypeName($_, 1) => 1} keys(%{$Type1{"SuperInterface"}});
    1662     my %SuperInterfaces_New = map {get_TypeName($_, 2) => 1} keys(%{$Type2{"SuperInterface"}});
     1054                    "Target"=>$SuperClassName1,
     1055                    "Old_Value"=>$SuperClassName1,
     1056                    "New_Value"=>$SuperClassName2);
     1057            }
     1058        }
     1059    }
     1060    my %SuperInterfaces_Old = map {getTypeName($_, 1) => 1} keys(%{$Type1{"SuperInterface"}});
     1061    my %SuperInterfaces_New = map {getTypeName($_, 2) => 1} keys(%{$Type2{"SuperInterface"}});
    16631062    foreach my $SuperInterface (keys(%SuperInterfaces_New))
    16641063    {
     
    16751074                    if($HaveMethods and checkDefaultImpl(2, $SuperInterface, $Type2{"Name"}))
    16761075                    {
    1677                         %{$SubProblems{"Interface_Added_Super_Interface_With_Implemented_Methods"}{get_SFormat($SuperInterface)}} = (
     1076                        %{$SubProblems{"Interface_Added_Super_Interface_With_Implemented_Methods"}{getSFormat($SuperInterface)}} = (
    16781077                            "Type_Name"=>$Type1{"Name"},
    1679                             "Target"=>$SuperInterface  );
     1078                            "Target"=>$SuperInterface);
    16801079                    }
    16811080                    else
     
    16831082                        if(my ($Invoked, $InvokedBy) = getInvoked($Type1{"Name"}))
    16841083                        {
    1685                             %{$SubProblems{"Interface_Added_Super_Interface_Used_By_Others"}{get_SFormat($SuperInterface)}} = (
     1084                            %{$SubProblems{"Interface_Added_Super_Interface_Used_By_Others"}{getSFormat($SuperInterface)}} = (
    16861085                                "Type_Name"=>$Type1{"Name"},
    16871086                                "Target"=>$SuperInterface,
    16881087                                "Invoked"=>$Invoked,
    1689                                 "InvokedBy"=>$InvokedBy  );
     1088                                "Invoked_By"=>$InvokedBy);
    16901089                        }
    16911090                        else
    16921091                        {
    1693                             %{$SubProblems{"Interface_Added_Super_Interface"}{get_SFormat($SuperInterface)}} = (
     1092                            %{$SubProblems{"Interface_Added_Super_Interface"}{getSFormat($SuperInterface)}} = (
    16941093                                "Type_Name"=>$Type1{"Name"},
    1695                                 "Target"=>$SuperInterface  );
     1094                                "Target"=>$SuperInterface);
    16961095                        }
    16971096                    }
     
    16991098                elsif($HaveFields)
    17001099                {
    1701                     %{$SubProblems{"Interface_Added_Super_Constant_Interface"}{get_SFormat($SuperInterface)}} = (
     1100                    %{$SubProblems{"Interface_Added_Super_Constant_Interface"}{getSFormat($SuperInterface)}} = (
    17021101                        "Type_Name"=>$Type2{"Name"},
    1703                         "Target"=>$SuperInterface  );
     1102                        "Target"=>$SuperInterface);
    17041103                }
    17051104                else
     
    17141113                    if($HaveMethods and checkDefaultImpl(2, $SuperInterface, $Type2{"Name"}))
    17151114                    {
    1716                         %{$SubProblems{"Abstract_Class_Added_Super_Interface_With_Implemented_Methods"}{get_SFormat($SuperInterface)}} = (
     1115                        %{$SubProblems{"Abstract_Class_Added_Super_Interface_With_Implemented_Methods"}{getSFormat($SuperInterface)}} = (
    17171116                            "Type_Name"=>$Type1{"Name"},
    1718                             "Target"=>$SuperInterface  );
     1117                            "Target"=>$SuperInterface);
    17191118                    }
    17201119                    else
     
    17221121                        if(my ($Invoked, $InvokedBy) = getInvoked($Type1{"Name"}))
    17231122                        {
    1724                             %{$SubProblems{"Abstract_Class_Added_Super_Interface_Invoked_By_Others"}{get_SFormat($SuperInterface)}} = (
     1123                            %{$SubProblems{"Abstract_Class_Added_Super_Interface_Invoked_By_Others"}{getSFormat($SuperInterface)}} = (
    17251124                                "Type_Name"=>$Type1{"Name"},
    17261125                                "Target"=>$SuperInterface,
    17271126                                "Invoked"=>$Invoked,
    1728                                 "InvokedBy"=>$InvokedBy  );
     1127                                "Invoked_By"=>$InvokedBy);
    17291128                        }
    17301129                        else
    17311130                        {
    1732                             %{$SubProblems{"Abstract_Class_Added_Super_Interface"}{get_SFormat($SuperInterface)}} = (
     1131                            %{$SubProblems{"Abstract_Class_Added_Super_Interface"}{getSFormat($SuperInterface)}} = (
    17331132                                "Type_Name"=>$Type1{"Name"},
    1734                                 "Target"=>$SuperInterface  );
     1133                                "Target"=>$SuperInterface);
    17351134                        }
    17361135                    }
     
    17511150                or $SuperInterface=~/\Ajava\./)
    17521151                {
    1753                     %{$SubProblems{"Interface_Removed_Super_Interface"}{get_SFormat($SuperInterface)}} = (
     1152                    %{$SubProblems{"Interface_Removed_Super_Interface"}{getSFormat($SuperInterface)}} = (
    17541153                        "Type_Name"=>$Type1{"Name"},
    17551154                        "Type_Type"=>"interface",
    1756                         "Target"=>$SuperInterface  );
     1155                        "Target"=>$SuperInterface);
    17571156                }
    17581157                elsif($HaveFields)
    17591158                {
    1760                     %{$SubProblems{"Interface_Removed_Super_Constant_Interface"}{get_SFormat($SuperInterface)}} = (
     1159                    %{$SubProblems{"Interface_Removed_Super_Constant_Interface"}{getSFormat($SuperInterface)}} = (
    17611160                        "Type_Name"=>$Type1{"Name"},
    1762                         "Target"=>$SuperInterface  );
     1161                        "Target"=>$SuperInterface);
    17631162                }
    17641163                else {
     
    17681167            else
    17691168            {
    1770                 %{$SubProblems{"Class_Removed_Super_Interface"}{get_SFormat($SuperInterface)}} = (
     1169                %{$SubProblems{"Class_Removed_Super_Interface"}{getSFormat($SuperInterface)}} = (
    17711170                    "Type_Name"=>$Type1{"Name"},
    17721171                    "Type_Type"=>"class",
    1773                     "Target"=>$SuperInterface  );
     1172                    "Target"=>$SuperInterface);
    17741173            }
    17751174        }
     
    17851184        my $Field_Pos1 = $Type1{"Fields"}{$Field_Name}{"Pos"};
    17861185        my $FieldType1_Id = $Type1{"Fields"}{$Field_Name}{"Type"};
    1787         my %FieldType1 = get_Type($FieldType1_Id, 1);
     1186        my $FieldType1_Name = getTypeName($FieldType1_Id, 1);
    17881187       
    17891188        if(not $Type2{"Fields"}{$Field_Name})
     
    17911190            my $StraightPair_Name = findFieldPair($Field_Pos1, \%Type2);
    17921191            if($StraightPair_Name ne "lost" and not $Type1{"Fields"}{$StraightPair_Name}
    1793             and $FieldType1{"Name"} eq get_TypeName($Type2{"Fields"}{$StraightPair_Name}{"Type"}, 2))
    1794             {
    1795                 if(my $Constant = get_ConstantValue($Type1{"Fields"}{$Field_Name}{"Value"}, $FieldType1{"Name"}))
     1192            and $FieldType1_Name eq getTypeName($Type2{"Fields"}{$StraightPair_Name}{"Type"}, 2))
     1193            {
     1194                if(my $Constant = getConstantValue($Type1{"Fields"}{$Field_Name}{"Value"}, $FieldType1_Name))
    17961195                {
    17971196                    %{$SubProblems{"Renamed_Constant_Field"}{$Field_Name}}=(
     
    18001199                        "Old_Value"=>$Field_Name,
    18011200                        "New_Value"=>$StraightPair_Name,
    1802                         "Field_Type"=>$FieldType1{"Name"},
    1803                         "Field_Value"=>$Constant  );
     1201                        "Field_Type"=>$FieldType1_Name,
     1202                        "Field_Value"=>$Constant);
    18041203                }
    18051204                else
     
    18101209                        "Old_Value"=>$Field_Name,
    18111210                        "New_Value"=>$StraightPair_Name,
    1812                         "Field_Type"=>$FieldType1{"Name"}  );
     1211                        "Field_Type"=>$FieldType1_Name);
    18131212                }
    18141213            }
    18151214            else
    18161215            {
    1817                 if(my $Constant = get_ConstantValue($Type1{"Fields"}{$Field_Name}{"Value"}, $FieldType1{"Name"}))
     1216                if(my $Constant = getConstantValue($Type1{"Fields"}{$Field_Name}{"Value"}, $FieldType1_Name))
    18181217                { # has a compile-time constant value
    18191218                    %{$SubProblems{"Removed_Constant_Field"}{$Field_Name}}=(
     
    18211220                        "Type_Name"=>$Type1{"Name"},
    18221221                        "Field_Value"=>$Constant,
    1823                         "Field_Type"=>$FieldType1{"Name"},
    1824                         "Type_Type"=>$Type1{"Type"}  );
     1222                        "Field_Type"=>$FieldType1_Name,
     1223                        "Type_Type"=>$Type1{"Type"});
    18251224                }
    18261225                else
     
    18301229                        "Type_Name"=>$Type1{"Name"},
    18311230                        "Type_Type"=>$Type1{"Type"},
    1832                         "Field_Type"=>$FieldType1{"Name"}  );
     1231                        "Field_Type"=>$FieldType1_Name);
    18331232                }
    18341233            }
    18351234            next;
    18361235        }
     1236       
    18371237        my $FieldType2_Id = $Type2{"Fields"}{$Field_Name}{"Type"};
    1838         my %FieldType2 = get_Type($FieldType2_Id, 2);
     1238        my $FieldType2_Name = getTypeName($FieldType2_Id, 2);
    18391239       
    18401240        if(not $Type1{"Fields"}{$Field_Name}{"Static"}
     
    18451245                %{$SubProblems{"NonConstant_Field_Became_Static"}{$Field_Name}}=(
    18461246                    "Target"=>$Field_Name,
    1847                     "Field_Type"=>$FieldType1{"Name"},
    1848                     "Type_Name"=>$Type1{"Name"}  );
     1247                    "Field_Type"=>$FieldType1_Name,
     1248                    "Type_Name"=>$Type1{"Name"});
    18491249            }
    18501250        }
     
    18561256                %{$SubProblems{"Constant_Field_Became_NonStatic"}{$Field_Name}}=(
    18571257                    "Target"=>$Field_Name,
    1858                     "Field_Type"=>$FieldType1{"Name"},
    1859                     "Type_Name"=>$Type1{"Name"}  );
     1258                    "Field_Type"=>$FieldType1_Name,
     1259                    "Type_Name"=>$Type1{"Name"});
    18601260            }
    18611261            else
     
    18631263                %{$SubProblems{"NonConstant_Field_Became_NonStatic"}{$Field_Name}}=(
    18641264                    "Target"=>$Field_Name,
    1865                     "Field_Type"=>$FieldType1{"Name"},
    1866                     "Type_Name"=>$Type1{"Name"}  );
     1265                    "Field_Type"=>$FieldType1_Name,
     1266                    "Type_Name"=>$Type1{"Name"});
    18671267            }
    18681268        }
     
    18721272            %{$SubProblems{"Field_Became_Final"}{$Field_Name}}=(
    18731273                "Target"=>$Field_Name,
    1874                 "Field_Type"=>$FieldType1{"Name"},
    1875                 "Type_Name"=>$Type1{"Name"}  );
     1274                "Field_Type"=>$FieldType1_Name,
     1275                "Type_Name"=>$Type1{"Name"});
    18761276        }
    18771277        elsif($Type1{"Fields"}{$Field_Name}{"Final"}
     
    18801280            %{$SubProblems{"Field_Became_NonFinal"}{$Field_Name}}=(
    18811281                "Target"=>$Field_Name,
    1882                 "Field_Type"=>$FieldType1{"Name"},
    1883                 "Type_Name"=>$Type1{"Name"}  );
     1282                "Field_Type"=>$FieldType1_Name,
     1283                "Type_Name"=>$Type1{"Name"});
    18841284        }
    18851285        my $Access2 = $Type2{"Fields"}{$Field_Name}{"Access"};
     
    18871287        or $Access1 eq "protected" and $Access2=~/private/)
    18881288        {
    1889             %{$SubProblems{"Changed_Field_Access"}{$Field_Name}}=(
    1890                 "Target"=>$Field_Name,
    1891                 "Type_Name"=>$Type1{"Name"},
    1892                 "Old_Value"=>$Access1,
    1893                 "New_Value"=>$Access2  );
    1894         }
    1895        
    1896         my $Value1 = get_ConstantValue($Type1{"Fields"}{$Field_Name}{"Value"}, $FieldType1{"Name"});
    1897         my $Value2 = get_ConstantValue($Type2{"Fields"}{$Field_Name}{"Value"}, $FieldType2{"Name"});
     1289            if($Access2 eq "package-private")
     1290            {
     1291                %{$SubProblems{"Changed_Field_Access_To_Package_Private"}{$Field_Name}}=(
     1292                    "Target"=>$Field_Name,
     1293                    "Type_Name"=>$Type1{"Name"},
     1294                    "Old_Value"=>$Access1,
     1295                    "New_Value"=>$Access2);
     1296            }
     1297            else
     1298            {
     1299                %{$SubProblems{"Changed_Field_Access"}{$Field_Name}}=(
     1300                    "Target"=>$Field_Name,
     1301                    "Type_Name"=>$Type1{"Name"},
     1302                    "Old_Value"=>$Access1,
     1303                    "New_Value"=>$Access2);
     1304            }
     1305        }
     1306       
     1307        my $Value1 = getConstantValue($Type1{"Fields"}{$Field_Name}{"Value"}, $FieldType1_Name);
     1308        my $Value2 = getConstantValue($Type2{"Fields"}{$Field_Name}{"Value"}, $FieldType2_Name);
    18981309       
    18991310        if($Value1 ne $Value2)
     
    19081319                        %{$SubProblems{"Changed_Final_Version_Field_Value"}{$Field_Name}}=(
    19091320                            "Target"=>$Field_Name,
    1910                             "Field_Type"=>$FieldType1{"Name"},
     1321                            "Field_Type"=>$FieldType1_Name,
    19111322                            "Type_Name"=>$Type1{"Name"},
    19121323                            "Old_Value"=>$Value1,
    1913                             "New_Value"=>$Value2  );
     1324                            "New_Value"=>$Value2);
    19141325                    }
    19151326                    else
     
    19171328                        %{$SubProblems{"Changed_Final_Field_Value"}{$Field_Name}}=(
    19181329                            "Target"=>$Field_Name,
    1919                             "Field_Type"=>$FieldType1{"Name"},
     1330                            "Field_Type"=>$FieldType1_Name,
    19201331                            "Type_Name"=>$Type1{"Name"},
    19211332                            "Old_Value"=>$Value1,
    1922                             "New_Value"=>$Value2  );
     1333                            "New_Value"=>$Value2);
    19231334                    }
    19241335                }
     
    19481359                foreach my $Sub_SubLocation (sort {length($a)<=>length($b)} sort keys(%{$Sub_SubProblems->{$Sub_SubProblemType}}))
    19491360                {
    1950                     if(not defined $AllAffected)
     1361                    if(not defined $In::Opt{"AllAffected"})
    19511362                    {
    19521363                        if(defined $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}}) {
     
    19581369                    $SubProblems{$Sub_SubProblemType}{$NewLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
    19591370                   
    1960                     if(not defined $AllAffected)
     1371                    if(not defined $In::Opt{"AllAffected"})
    19611372                    {
    19621373                        $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}} = 1;
     
    19751386        my $FieldPos2 = $Type2{"Fields"}{$Field_Name}{"Pos"};
    19761387        my $FieldType2_Id = $Type2{"Fields"}{$Field_Name}{"Type"};
    1977         my %FieldType2 = get_Type($FieldType2_Id, 2);
     1388        my $FieldType2_Name = getTypeName($FieldType2_Id, 2);
    19781389       
    19791390        if(not $Type1{"Fields"}{$Field_Name})
     
    19811392            my $StraightPair_Name = findFieldPair($FieldPos2, \%Type1);
    19821393            if($StraightPair_Name ne "lost" and not $Type2{"Fields"}{$StraightPair_Name}
    1983             and get_TypeName($Type1{"Fields"}{$StraightPair_Name}{"Type"}, 1) eq $FieldType2{"Name"})
     1394            and getTypeName($Type1{"Fields"}{$StraightPair_Name}{"Type"}, 1) eq $FieldType2_Name)
    19841395            {
    19851396                # Already reported as "Renamed_Field" or "Renamed_Constant_Field"
     
    19911402                    %{$SubProblems{"Interface_Added_Field"}{$Field_Name}}=(
    19921403                        "Target"=>$Field_Name,
    1993                         "Type_Name"=>$Type1{"Name"}  );
     1404                        "Type_Name"=>$Type1{"Name"});
    19941405                }
    19951406                else
     
    19971408                    %{$SubProblems{"Class_Added_Field"}{$Field_Name}}=(
    19981409                        "Target"=>$Field_Name,
    1999                         "Type_Name"=>$Type1{"Name"}  );
     1410                        "Type_Name"=>$Type1{"Name"});
    20001411                }
    20011412            }
     
    20101421{ # Check if all abstract methods of the super class have
    20111422  # default implementations in the class
    2012     my ($LibVersion, $SuperClassName, $ClassName) = @_;
    2013    
    2014     foreach my $Method (keys(%{$Class_AbstractMethods{$LibVersion}{$SuperClassName}}))
    2015     {
    2016         if(my $Overridden = findMethod_Class($Method, $ClassName, $LibVersion))
    2017         {
    2018             if($MethodInfo{$LibVersion}{$Overridden}{"Abstract"}) {
     1423    my ($LVer, $SuperClassName, $ClassName) = @_;
     1424   
     1425    foreach my $Method (keys(%{$Class_AbstractMethods{$LVer}{$SuperClassName}}))
     1426    {
     1427        if(my $Overridden = findMethod_Class($Method, $ClassName, $LVer))
     1428        {
     1429            if($MethodInfo{$LVer}{$Overridden}{"Abstract"}) {
    20191430                return 0;
    20201431            }
     
    20281439}
    20291440
    2030 sub unmangle($)
    2031 {
    2032     my $Name = $_[0];
    2033     $Name=~s!/!.!g;
    2034     $Name=~s!:\(!(!g;
    2035     $Name=~s!\).+\Z!)!g;
    2036     if($Name=~/\A(.+)\((.+)\)/)
    2037     {
    2038         my ($ShortName, $MangledParams) = ($1, $2);
    2039         my @UnmangledParams = ();
    2040         my ($IsArray, $Shift, $Pos, $CurParam) = (0, 0, 0, "");
    2041         while($Pos<length($MangledParams))
    2042         {
    2043             my $Symbol = substr($MangledParams, $Pos, 1);
    2044             if($Symbol eq "[")
    2045             { # array
    2046                 $IsArray = 1;
    2047                 $Pos+=1;
    2048             }
    2049             elsif($Symbol eq "L")
    2050             { # class
    2051                 if(substr($MangledParams, $Pos+1)=~/\A(.+?);/) {
    2052                     $CurParam = $1;
    2053                     $Shift = length($CurParam)+2;
    2054                 }
    2055                 if($IsArray) {
    2056                     $CurParam .= "[]";
    2057                 }
    2058                 $Pos+=$Shift;
    2059                 push(@UnmangledParams, $CurParam);
    2060                 ($IsArray, $Shift, $CurParam) = (0, 0, "")
    2061             }
    2062             else
    2063             {
    2064                 if($Symbol eq "C") {
    2065                     $CurParam = "char";
    2066                 }
    2067                 elsif($Symbol eq "B") {
    2068                     $CurParam = "byte";
    2069                 }
    2070                 elsif($Symbol eq "S") {
    2071                     $CurParam = "short";
    2072                 }
    2073                 elsif($Symbol eq "S") {
    2074                     $CurParam = "short";
    2075                 }
    2076                 elsif($Symbol eq "I") {
    2077                     $CurParam = "int";
    2078                 }
    2079                 elsif($Symbol eq "F") {
    2080                     $CurParam = "float";
    2081                 }
    2082                 elsif($Symbol eq "J") {
    2083                     $CurParam = "long";
    2084                 }
    2085                 elsif($Symbol eq "D") {
    2086                     $CurParam = "double";
    2087                 }
    2088                 else {
    2089                     printMsg("INFO", "WARNING: unmangling error");
    2090                 }
    2091                 if($IsArray) {
    2092                     $CurParam .= "[]";
    2093                 }
    2094                 $Pos+=1;
    2095                 push(@UnmangledParams, $CurParam);
    2096                 ($IsArray, $Shift, $CurParam) = (0, 0, "")
    2097             }
    2098         }
    2099         return $ShortName."(".join(", ", @UnmangledParams).")";
    2100     }
    2101     else {
    2102         return $Name;
    2103     }
    2104 }
    2105 
    2106 sub get_TypeName($$)
    2107 {
    2108     my ($TypeId, $LibVersion) = @_;
    2109     return $TypeInfo{$LibVersion}{$TypeId}{"Name"};
    2110 }
    2111 
    2112 sub get_ShortName($$)
    2113 {
    2114     my ($TypeId, $LibVersion) = @_;
    2115     my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
    2116     $TypeName=~s/\A.*\.//g;
    2117     return $TypeName;
    2118 }
    2119 
    2120 sub get_TypeType($$)
    2121 {
    2122     my ($TypeId, $LibVersion) = @_;
    2123     return $TypeInfo{$LibVersion}{$TypeId}{"Type"};
    2124 }
    2125 
    2126 sub get_TypeHeader($$)
    2127 {
    2128     my ($TypeId, $LibVersion) = @_;
    2129     return $TypeInfo{$LibVersion}{$TypeId}{"Header"};
    2130 }
    2131 
    2132 sub get_BaseType($$)
    2133 {
    2134     my ($TypeId, $LibVersion) = @_;
    2135     return "" if(not $TypeId);
    2136     if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
    2137         return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
    2138     }
    2139     return "" if(not $TypeInfo{$LibVersion}{$TypeId});
    2140     my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
    2141     return %Type if(not $Type{"BaseType"});
    2142     %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
    2143     $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
    2144     return %Type;
    2145 }
    2146 
    2147 sub get_OneStep_BaseType($$)
    2148 {
    2149     my ($TypeId, $LibVersion) = @_;
    2150     return "" if(not $TypeId);
    2151     return "" if(not $TypeInfo{$LibVersion}{$TypeId});
    2152     my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
    2153     return %Type if(not $Type{"BaseType"});
    2154     return get_Type($Type{"BaseType"}, $LibVersion);
    2155 }
    2156 
    2157 sub get_Type($$)
    2158 {
    2159     my ($TypeId, $LibVersion) = @_;
    2160     return "" if(not $TypeId);
    2161     return "" if(not $TypeInfo{$LibVersion}{$TypeId});
    2162     return %{$TypeInfo{$LibVersion}{$TypeId}};
    2163 }
    2164 
    2165 sub classFilter($$$)
    2166 {
    2167     my ($Class, $LibVersion, $ClassContext) = @_;
    2168    
    2169     if(defined $Class->{"Dep"}) {
    2170         return 0;
    2171     }
    2172    
    2173     my $CName = $Class->{"Name"};
    2174     my $Package = $Class->{"Package"};
    2175    
    2176     if(defined $ClassListPath
    2177     and not defined $ClassList_User{$CName})
    2178     { # user defined classes
    2179         return 0;
    2180     }
    2181    
    2182     if(defined $SkipClassesList
    2183     and defined $SkipClasses{$CName})
    2184     { # user defined classes
    2185         return 0;
    2186     }
    2187    
    2188     if(skipPackage($Package, $LibVersion))
    2189     { # internal packages
    2190         return 0;
    2191     }
    2192    
    2193     if(skipType($CName))
    2194     { # internal types
    2195         return 0;
    2196     }
    2197    
    2198     if($ClassContext)
    2199     {
    2200         my @Ann = ();
    2201        
    2202         if(defined $Class->{"Annotations"}) {
    2203             @Ann = keys(%{$Class->{"Annotations"}});
    2204         }
    2205        
    2206         if(not annotationFilter(\@Ann, $LibVersion)) {
    2207             return 0;
    2208         }
    2209        
    2210         if($ClientPath)
    2211         {
    2212             if(not defined $UsedClasses_Client{$CName}) {
    2213                 return 0;
    2214             }
    2215         }
    2216     }
    2217    
    2218     return 1;
    2219 }
    2220 
    2221 sub annotationFilter($$)
    2222 {
    2223     my ($Ann, $LibVersion) = @_;
    2224    
    2225     if(not defined $CountMethods)
    2226     {
    2227         if(defined $AddedAnnotations and $LibVersion==1) {
    2228             return 1;
    2229         }
    2230        
    2231         if(defined $RemovedAnnotations and $LibVersion==2) {
    2232             return 1;
    2233         }
    2234     }
    2235    
    2236     if($SkipAnnotationsListPath)
    2237     {
    2238         foreach my $Aid (@{$Ann})
    2239         {
    2240             my $AName = $TypeInfo{$LibVersion}{$Aid}{"Name"};
    2241            
    2242             if(defined $SkipAnnotationList_User{$AName}) {
    2243                 return 0;
    2244             }
    2245         }
    2246     }
    2247    
    2248     if($AnnotationsListPath)
    2249     {
    2250         my $Annotated = 0;
    2251        
    2252         foreach my $Aid (@{$Ann})
    2253         {
    2254             my $AName = $TypeInfo{$LibVersion}{$Aid}{"Name"};
    2255            
    2256             if(defined $AnnotationList_User{$AName})
    2257             {
    2258                 $Annotated = 1;
    2259                 last;
    2260             }
    2261         }
    2262        
    2263         if(not $Annotated) {
    2264             return 0;
    2265         }
    2266     }
    2267    
    2268     return 1;
    2269 }
    2270 
    2271 sub methodFilter($$)
    2272 {
    2273     my ($Method, $LibVersion) = @_;
    2274    
    2275     if(defined $MethodInfo{$LibVersion}{$Method}{"Dep"}) {
    2276         return 0;
    2277     }
    2278    
    2279     if($MethodInfo{$LibVersion}{$Method}{"Access"}=~/private/)
    2280     { # non-public
    2281         return 0;
    2282     }
    2283    
    2284     my $ClassId = $MethodInfo{$LibVersion}{$Method}{"Class"};
    2285     my %Class = get_Type($ClassId, $LibVersion);
    2286    
    2287     if($Class{"Access"}=~/private/)
    2288     { # skip private classes
    2289         return 0;
    2290     }
    2291    
    2292     my $Package = $MethodInfo{$LibVersion}{$Method}{"Package"};
    2293    
    2294     my @Ann = ();
    2295    
    2296     if(defined $Class{"Annotations"}) {
    2297         @Ann = (@Ann, keys(%{$Class{"Annotations"}}));
    2298     }
    2299    
    2300     if(defined $MethodInfo{$LibVersion}{$Method}{"Annotations"}) {
    2301         @Ann = (@Ann, keys(%{$MethodInfo{$LibVersion}{$Method}{"Annotations"}}));
    2302     }
    2303    
    2304     if(not annotationFilter(\@Ann, $LibVersion)) {
    2305         return 0;
    2306     }
    2307    
    2308     if($ClientPath)
    2309     { # user defined application
    2310         if(not defined $UsedMethods_Client{$Method}
    2311         and not defined $UsedClasses_Client{$Class{"Name"}}) {
    2312             return 0;
    2313         }
    2314     }
    2315    
    2316     if(skipPackage($Package, $LibVersion))
    2317     { # internal packages
    2318         return 0;
    2319     }
    2320    
    2321     if(not classFilter(\%Class, $LibVersion, 0)) {
    2322         return 0;
    2323     }
    2324    
    2325     if(defined $SkipDeprecated)
    2326     {
    2327         if($Class{"Deprecated"})
    2328         { # deprecated class
    2329             return 0;
    2330         }
    2331         if($MethodInfo{$LibVersion}{$Method}{"Deprecated"})
    2332         { # deprecated method
    2333             return 0;
    2334         }
    2335     }
    2336    
    2337     return 1;
    2338 }
    2339 
    2340 sub skipType($)
    2341 {
    2342     my $TName = $_[0];
    2343    
    2344     if(defined $SkipInternalTypes)
    2345     {
    2346         if($TName=~/($SkipInternalTypes)/) {
    2347             return 1;
    2348         }
    2349     }
    2350    
    2351     return 0;
    2352 }
    2353 
    2354 sub skipPackage($$)
    2355 {
    2356     my ($Package, $LibVersion) = @_;
    2357     return 0 if(not $Package);
    2358    
    2359     if(defined $SkipInternalPackages)
    2360     {
    2361         if($Package=~/($SkipInternalPackages)/) {
    2362             return 1;
    2363         }
    2364     }
    2365    
    2366     if(defined $SkipPackages{$LibVersion})
    2367     {
    2368         foreach my $SkipPackage (keys(%{$SkipPackages{$LibVersion}}))
    2369         {
    2370             if($Package=~/\A\Q$SkipPackage\E(\.|\Z)/)
    2371             { # user skipped packages
    2372                 return 1;
    2373             }
    2374         }
    2375     }
    2376    
    2377     if(not defined $KeepInternal)
    2378     {
    2379         my $Note = (not keys %SkippedPackage)?" (use --keep-internal option to check them)":"";
    2380        
    2381         if($Package=~/(\A|\.)(internal|impl|examples)(\.|\Z)/)
    2382         { # internal packages
    2383             if(not $SkippedPackage{$LibVersion}{$2})
    2384             {
    2385                 $SkippedPackage{$LibVersion}{$2} = 1;
    2386                 printMsg("WARNING", "skip \"$2\" packages".$Note);
    2387             }
    2388             return 1;
    2389         }
    2390     }
    2391    
    2392     if(defined $KeepPackages{$LibVersion}
    2393     and my @Keeped = keys(%{$KeepPackages{$LibVersion}}))
    2394     {
    2395         my $UserKeeped = 0;
    2396         foreach my $KeepPackage (@Keeped)
    2397         {
    2398             if($Package=~/\A\Q$KeepPackage\E(\.|\Z)/)
    2399             { # user keeped packages
    2400                 $UserKeeped = 1;
    2401                 last;
    2402             }
    2403         }
    2404         if(not $UserKeeped) {
    2405             return 1;
    2406         }
    2407     }
    2408    
    2409     return 0;
    2410 }
    2411 
    2412 sub get_MSuffix($)
     1441sub getMSuffix($)
    24131442{
    24141443    my $Method = $_[0];
     
    24191448}
    24201449
    2421 sub get_MShort($)
     1450sub getMShort($)
    24221451{
    24231452    my $Method = $_[0];
     
    24361465    {
    24371466        my @Search = ();
    2438         if(get_TypeType($ClassId, $ClassVersion) eq "class")
     1467        if(getTypeType($ClassId, $ClassVersion) eq "class")
    24391468        {
    24401469            if(my $SuperClassId = $TypeInfo{$ClassVersion}{$ClassId}{"SuperClass"}) {
     
    24571486            }
    24581487           
    2459             my $SuperName = get_TypeName($SuperId, $ClassVersion);
     1488            my $SuperName = getTypeName($SuperId, $ClassVersion);
    24601489           
    24611490            if(my $MethodInClass = findMethod_Class($Method, $SuperName, $ClassVersion)) {
     
    24681497    }
    24691498   
    2470     my $TargetSuffix = get_MSuffix($Method);
    2471     my $TargetShortName = get_MShort($Method);
     1499    my $TargetSuffix = getMSuffix($Method);
     1500    my $TargetShortName = getMShort($Method);
    24721501   
    24731502    # search in java.lang.Object
    24741503    foreach my $C (keys(%JavaObjectMethod))
    24751504    {
    2476         if($TargetSuffix eq get_MSuffix($C))
    2477         {
    2478             if($TargetShortName eq get_MShort($C)) {
     1505        if($TargetSuffix eq getMSuffix($C))
     1506        {
     1507            if($TargetShortName eq getMShort($C)) {
    24791508                return $C;
    24801509            }
     
    24881517{
    24891518    my ($Method, $ClassName, $ClassVersion) = @_;
    2490     my $TargetSuffix = get_MSuffix($Method);
    2491     my $TargetShortName = get_MShort($Method);
     1519    my $TargetSuffix = getMSuffix($Method);
     1520    my $TargetShortName = getMShort($Method);
    24921521   
    24931522    if(not defined $Class_Methods{$ClassVersion}{$ClassName}) {
     
    24981527    { # search for method with the same parameters suffix
    24991528        next if($MethodInfo{$ClassVersion}{$Candidate}{"Constructor"});
    2500         if($TargetSuffix eq get_MSuffix($Candidate))
    2501         {
    2502             if($TargetShortName eq get_MShort($Candidate)) {
     1529        if($TargetSuffix eq getMSuffix($Candidate))
     1530        {
     1531            if($TargetShortName eq getMShort($Candidate)) {
    25031532                return $Candidate;
    25041533            }
     
    25091538}
    25101539
    2511 sub prepareMethods($)
    2512 {
    2513     my $LibVersion = $_[0];
    2514     foreach my $Method (keys(%{$MethodInfo{$LibVersion}}))
    2515     {
    2516         if($MethodInfo{$LibVersion}{$Method}{"Access"}!~/private/)
    2517         {
    2518             if($MethodInfo{$LibVersion}{$Method}{"Constructor"}) {
    2519                 registerUsage($MethodInfo{$LibVersion}{$Method}{"Class"}, $LibVersion);
     1540sub prepareData($)
     1541{
     1542    my $LVer = $_[0];
     1543   
     1544    if(my $MUsed = $In::API{$LVer}{"MethodUsed"})
     1545    {
     1546        foreach my $M_Id (keys(%{$MUsed}))
     1547        {
     1548            my $Name = $MUsed->{$M_Id}{"Name"};
     1549            $MethodUsed{$LVer}{$Name} = $MUsed->{$M_Id}{"Used"};
     1550        }
     1551    }
     1552   
     1553    foreach my $TypeId (keys(%{$TypeInfo{$LVer}}))
     1554    {
     1555        my $TypeAttr = $TypeInfo{$LVer}{$TypeId};
     1556        my $TName = $TypeAttr->{"Name"};
     1557       
     1558        $TName_Tid{$LVer}{$TName} = $TypeId;
     1559       
     1560        if(not $TypeAttr->{"Dep"})
     1561        {
     1562            if(my $Archive = $TypeAttr->{"Archive"}) {
     1563                $LibArchives{$LVer}{$Archive} = 1;
     1564            }
     1565        }
     1566       
     1567        foreach my $FieldName (keys(%{$TypeAttr->{"Fields"}}))
     1568        {
     1569            if($TypeAttr->{"Fields"}{$FieldName}{"Access"}=~/public|protected/) {
     1570                $Class_Fields{$LVer}{$TName}{$FieldName} = $TypeAttr->{"Fields"}{$FieldName}{"Type"};
     1571            }
     1572        }
     1573    }
     1574   
     1575    foreach my $Method (keys(%{$MethodInfo{$LVer}}))
     1576    {
     1577        my $Name = $MethodInfo{$LVer}{$Method}{"Name"};
     1578        $MethodInfo{$LVer}{$Name} = delete($MethodInfo{$LVer}{$Method});
     1579    }
     1580   
     1581    foreach my $Method (keys(%{$MethodInfo{$LVer}}))
     1582    {
     1583        my $MAttr = $MethodInfo{$LVer}{$Method};
     1584       
     1585        $MAttr->{"Signature"} = getSignature($Method, $LVer, "Full");
     1586       
     1587        if(my $ClassId = $MAttr->{"Class"}
     1588        and $MAttr->{"Access"}=~/public|protected/)
     1589        {
     1590            my $CName = getTypeName($ClassId, $LVer);
     1591            $Class_Methods{$LVer}{$CName}{$Method} = 1;
     1592            if($MAttr->{"Abstract"}) {
     1593                $Class_AbstractMethods{$LVer}{$CName}{$Method} = 1;
     1594            }
     1595        }
     1596       
     1597        if($MAttr->{"Access"}!~/private/)
     1598        {
     1599            if($MAttr->{"Constructor"}) {
     1600                registerUsage($MAttr->{"Class"}, $LVer);
    25201601            }
    25211602            else {
    2522                 registerUsage($MethodInfo{$LibVersion}{$Method}{"Return"}, $LibVersion);
     1603                registerUsage($MAttr->{"Return"}, $LVer);
    25231604            }
    25241605        }
     
    25421623       
    25431624        my $ClassId1 = $MethodInfo{1}{$Method}{"Class"};
    2544         my %Class1 = get_Type($ClassId1, 1);
    2545        
    2546         $CheckedTypes{$Class1{"Name"}} = 1;
     1625        my $Class1_Name = getTypeName($ClassId1, 1);
     1626        my $Class1_Type = getTypeType($ClassId1, 1);
     1627       
     1628        $CheckedTypes{$Class1_Name} = 1;
    25471629        $CheckedMethods{$Method} = 1;
    25481630       
    2549         my %Class2 = get_Type($MethodInfo{2}{$Method}{"Class"}, 2);
    25501631        if(not $MethodInfo{1}{$Method}{"Static"}
    2551         and $Class1{"Type"} eq "class" and not $Class_Constructed{1}{$ClassId1})
     1632        and $Class1_Type eq "class" and not $Class_Constructed{1}{$ClassId1})
    25521633        { # class cannot be constructed or inherited by clients
    25531634          # non-static method cannot be called
    25541635            next;
    25551636        }
     1637       
    25561638        # checking attributes
    25571639        if(not $MethodInfo{1}{$Method}{"Static"}
     
    25631645            %{$CompatProblems{$Method}{"Method_Became_NonStatic"}{""}} = ();
    25641646        }
     1647       
    25651648        if(not $MethodInfo{1}{$Method}{"Synchronized"}
    25661649        and $MethodInfo{2}{$Method}{"Synchronized"}) {
     
    25711654            %{$CompatProblems{$Method}{"Method_Became_NonSynchronized"}{""}} = ();
    25721655        }
     1656       
    25731657        if(not $MethodInfo{1}{$Method}{"Final"}
    25741658        and $MethodInfo{2}{$Method}{"Final"})
     
    25811665            }
    25821666        }
     1667       
    25831668        my $Access1 = $MethodInfo{1}{$Method}{"Access"};
    25841669        my $Access2 = $MethodInfo{2}{$Method}{"Access"};
     1670       
    25851671        if($Access1 eq "public" and $Access2=~/protected|private/
    25861672        or $Access1 eq "protected" and $Access2=~/private/)
     
    25881674            %{$CompatProblems{$Method}{"Changed_Method_Access"}{""}} = (
    25891675                "Old_Value"=>$Access1,
    2590                 "New_Value"=>$Access2  );
    2591         }
    2592         if($Class1{"Type"} eq "class"
    2593         and $Class2{"Type"} eq "class")
     1676                "New_Value"=>$Access2);
     1677        }
     1678       
     1679        my $Class2_Type = getTypeType($MethodInfo{2}{$Method}{"Class"}, 2);
     1680       
     1681        if($Class1_Type eq "class"
     1682        and $Class2_Type eq "class")
    25941683        {
    25951684            if(not $MethodInfo{1}{$Method}{"Abstract"}
     
    25971686            {
    25981687                %{$CompatProblems{$Method}{"Method_Became_Abstract"}{""}} = ();
    2599                 %{$CompatProblems{$Method}{"Class_Method_Became_Abstract"}{"this.".get_SFormat($Method)}} = (
    2600                     "Type_Name"=>$Class1{"Name"},
    2601                     "Target"=>$Method  );
     1688                %{$CompatProblems{$Method}{"Class_Method_Became_Abstract"}{"this.".getSFormat($Method)}} = (
     1689                    "Type_Name"=>$Class1_Name,
     1690                    "Target"=>$Method);
    26021691            }
    26031692            elsif($MethodInfo{1}{$Method}{"Abstract"}
     
    26051694            {
    26061695                %{$CompatProblems{$Method}{"Method_Became_NonAbstract"}{""}} = ();
    2607                 %{$CompatProblems{$Method}{"Class_Method_Became_NonAbstract"}{"this.".get_SFormat($Method)}} = (
    2608                     "Type_Name"=>$Class1{"Name"},
    2609                     "Target"=>$Method  );
    2610             }
    2611         }
    2612         elsif($Class1{"Type"} eq "interface"
    2613         and $Class2{"Type"} eq "interface")
     1696                %{$CompatProblems{$Method}{"Class_Method_Became_NonAbstract"}{"this.".getSFormat($Method)}} = (
     1697                    "Type_Name"=>$Class1_Name,
     1698                    "Target"=>$Method);
     1699            }
     1700        }
     1701        elsif($Class1_Type eq "interface"
     1702        and $Class2_Type eq "interface")
    26141703        {
    26151704            if(not $MethodInfo{1}{$Method}{"Abstract"}
     
    26171706            {
    26181707                %{$CompatProblems{$Method}{"Method_Became_NonDefault"}{""}} = ();
    2619                 %{$CompatProblems{$Method}{"Interface_Method_Became_NonDefault"}{"this.".get_SFormat($Method)}} = (
    2620                     "Type_Name"=>$Class1{"Name"},
    2621                     "Target"=>$Method  );
     1708                %{$CompatProblems{$Method}{"Interface_Method_Became_NonDefault"}{"this.".getSFormat($Method)}} = (
     1709                    "Type_Name"=>$Class1_Name,
     1710                    "Target"=>$Method);
    26221711            }
    26231712            elsif($MethodInfo{1}{$Method}{"Abstract"}
     
    26251714            {
    26261715                %{$CompatProblems{$Method}{"Method_Became_Default"}{""}} = ();
    2627                 %{$CompatProblems{$Method}{"Interface_Method_Became_Default"}{"this.".get_SFormat($Method)}} = (
    2628                     "Type_Name"=>$Class1{"Name"},
    2629                     "Target"=>$Method  );
    2630             }
    2631         }
    2632        
    2633         my %Exceptions_Old = map {get_TypeName($_, 1) => $_} keys(%{$MethodInfo{1}{$Method}{"Exceptions"}});
    2634         my %Exceptions_New = map {get_TypeName($_, 2) => $_} keys(%{$MethodInfo{2}{$Method}{"Exceptions"}});
     1716                %{$CompatProblems{$Method}{"Interface_Method_Became_Default"}{"this.".getSFormat($Method)}} = (
     1717                    "Type_Name"=>$Class1_Name,
     1718                    "Target"=>$Method);
     1719            }
     1720        }
     1721       
     1722        my %Exceptions_Old = map {getTypeName($_, 1) => $_} keys(%{$MethodInfo{1}{$Method}{"Exceptions"}});
     1723        my %Exceptions_New = map {getTypeName($_, 2) => $_} keys(%{$MethodInfo{2}{$Method}{"Exceptions"}});
    26351724        foreach my $Exception (keys(%Exceptions_Old))
    26361725        {
    26371726            if(not $Exceptions_New{$Exception})
    26381727            {
    2639                 my %ExceptionType = get_Type($Exceptions_Old{$Exception}, 1);
    2640                 my $SuperClass = $ExceptionType{"SuperClass"};
     1728                my $EType = getType($Exceptions_Old{$Exception}, 1);
     1729                my $SuperClass = $EType->{"SuperClass"};
     1730               
    26411731                if($KnownRuntimeExceptions{$Exception}
    2642                 or defined $SuperClass and get_TypeName($SuperClass, 1) eq "java.lang.RuntimeException")
     1732                or defined $SuperClass and getTypeName($SuperClass, 1) eq "java.lang.RuntimeException")
    26431733                {
    26441734                    if(not $MethodInfo{1}{$Method}{"Abstract"}
    26451735                    and not $MethodInfo{2}{$Method}{"Abstract"})
    26461736                    {
    2647                         %{$CompatProblems{$Method}{"Removed_Unchecked_Exception"}{"this.".get_SFormat($Exception)}} = (
    2648                             "Type_Name"=>$Class1{"Name"},
    2649                             "Target"=>$Exception  );
     1737                        %{$CompatProblems{$Method}{"Removed_Unchecked_Exception"}{"this.".getSFormat($Exception)}} = (
     1738                            "Type_Name"=>$Class1_Name,
     1739                            "Target"=>$Exception);
    26501740                    }
    26511741                }
     
    26551745                    and $MethodInfo{2}{$Method}{"Abstract"})
    26561746                    {
    2657                         %{$CompatProblems{$Method}{"Abstract_Method_Removed_Checked_Exception"}{"this.".get_SFormat($Exception)}} = (
    2658                             "Type_Name"=>$Class1{"Name"},
    2659                             "Target"=>$Exception  );
     1747                        %{$CompatProblems{$Method}{"Abstract_Method_Removed_Checked_Exception"}{"this.".getSFormat($Exception)}} = (
     1748                            "Type_Name"=>$Class1_Name,
     1749                            "Target"=>$Exception);
    26601750                    }
    26611751                    else
    26621752                    {
    2663                         %{$CompatProblems{$Method}{"NonAbstract_Method_Removed_Checked_Exception"}{"this.".get_SFormat($Exception)}} = (
    2664                             "Type_Name"=>$Class1{"Name"},
    2665                             "Target"=>$Exception  );
    2666                     }
    2667                 }
    2668             }
    2669         }
     1753                        %{$CompatProblems{$Method}{"NonAbstract_Method_Removed_Checked_Exception"}{"this.".getSFormat($Exception)}} = (
     1754                            "Type_Name"=>$Class1_Name,
     1755                            "Target"=>$Exception);
     1756                    }
     1757                }
     1758            }
     1759        }
     1760       
    26701761        foreach my $Exception (keys(%Exceptions_New))
    26711762        {
    26721763            if(not $Exceptions_Old{$Exception})
    26731764            {
    2674                 my %ExceptionType = get_Type($Exceptions_New{$Exception}, 2);
    2675                 my $SuperClass = $ExceptionType{"SuperClass"};
     1765                my $EType = getType($Exceptions_New{$Exception}, 2);
     1766                my $SuperClass = $EType->{"SuperClass"};
     1767               
    26761768                if($KnownRuntimeExceptions{$Exception}
    2677                 or defined $SuperClass and get_TypeName($SuperClass, 2) eq "java.lang.RuntimeException")
     1769                or defined $SuperClass and getTypeName($SuperClass, 2) eq "java.lang.RuntimeException")
    26781770                {
    26791771                    if(not $MethodInfo{1}{$Method}{"Abstract"}
    26801772                    and not $MethodInfo{2}{$Method}{"Abstract"})
    26811773                    {
    2682                         %{$CompatProblems{$Method}{"Added_Unchecked_Exception"}{"this.".get_SFormat($Exception)}} = (
    2683                             "Type_Name"=>$Class1{"Name"},
    2684                             "Target"=>$Exception  );
     1774                        %{$CompatProblems{$Method}{"Added_Unchecked_Exception"}{"this.".getSFormat($Exception)}} = (
     1775                            "Type_Name"=>$Class1_Name,
     1776                            "Target"=>$Exception);
    26851777                    }
    26861778                }
     
    26901782                    and $MethodInfo{2}{$Method}{"Abstract"})
    26911783                    {
    2692                         %{$CompatProblems{$Method}{"Abstract_Method_Added_Checked_Exception"}{"this.".get_SFormat($Exception)}} = (
    2693                             "Type_Name"=>$Class1{"Name"},
    2694                             "Target"=>$Exception  );
     1784                        %{$CompatProblems{$Method}{"Abstract_Method_Added_Checked_Exception"}{"this.".getSFormat($Exception)}} = (
     1785                            "Type_Name"=>$Class1_Name,
     1786                            "Target"=>$Exception);
    26951787                    }
    26961788                    else
    26971789                    {
    2698                         %{$CompatProblems{$Method}{"NonAbstract_Method_Added_Checked_Exception"}{"this.".get_SFormat($Exception)}} = (
    2699                             "Type_Name"=>$Class1{"Name"},
    2700                             "Target"=>$Exception  );
     1790                        %{$CompatProblems{$Method}{"NonAbstract_Method_Added_Checked_Exception"}{"this.".getSFormat($Exception)}} = (
     1791                            "Type_Name"=>$Class1_Name,
     1792                            "Target"=>$Exception);
    27011793                    }
    27021794                }
     
    27791871    my ($Type1_Id, $Type2_Id, $Prefix) = @_;
    27801872    my %LocalProblems = ();
    2781     my %Type1 = get_Type($Type1_Id, 1);
    2782     my %Type2 = get_Type($Type2_Id, 2);
    2783     my %Type1_Base = ($Type1{"Type"} eq "array")?get_OneStep_BaseType($Type1_Id, 1):get_BaseType($Type1_Id, 1);
    2784     my %Type2_Base = ($Type2{"Type"} eq "array")?get_OneStep_BaseType($Type2_Id, 2):get_BaseType($Type2_Id, 2);
    2785     return () if(not $Type1{"Name"} or not $Type2{"Name"});
    2786     return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
    2787     if($Type1_Base{"Name"} ne $Type2_Base{"Name"} and $Type1{"Name"} eq $Type2{"Name"})
     1873   
     1874    my $Type1 = getType($Type1_Id, 1);
     1875    my $Type2 = getType($Type2_Id, 2);
     1876   
     1877    my $Type1_Name = $Type1->{"Name"};
     1878    my $Type2_Name = $Type2->{"Name"};
     1879   
     1880    my $Type1_Base = undef;
     1881    my $Type2_Base = undef;
     1882   
     1883    if($Type1->{"Type"} eq "array") {
     1884        $Type1_Base = getOneStepBaseType($Type1_Id, 1);
     1885    }
     1886    else {
     1887        $Type1_Base = getBaseType($Type1_Id, 1);
     1888    }
     1889   
     1890    if($Type2->{"Type"} eq "array") {
     1891        $Type2_Base = getOneStepBaseType($Type2_Id, 2);
     1892    }
     1893    else {
     1894        $Type2_Base = getBaseType($Type2_Id, 2);
     1895    }
     1896   
     1897    return () if(not $Type1_Name or not $Type2_Name);
     1898    return () if(not $Type1_Base->{"Name"} or not $Type2_Base->{"Name"});
     1899    if($Type1_Base->{"Name"} ne $Type2_Base->{"Name"} and $Type1_Name eq $Type2_Name)
    27881900    {# base type change
    27891901        %{$LocalProblems{"Changed_".$Prefix."_BaseType"}}=(
    2790             "Old_Value"=>$Type1_Base{"Name"},
    2791             "New_Value"=>$Type2_Base{"Name"} );
    2792     }
    2793     elsif($Type1{"Name"} ne $Type2{"Name"})
     1902            "Old_Value"=>$Type1_Base->{"Name"},
     1903            "New_Value"=>$Type2_Base->{"Name"});
     1904    }
     1905    elsif($Type1_Name ne $Type2_Name)
    27941906    {# type change
    27951907        %{$LocalProblems{"Changed_".$Prefix."_Type"}}=(
    2796             "Old_Value"=>$Type1{"Name"},
    2797             "New_Value"=>$Type2{"Name"} );
     1908            "Old_Value"=>$Type1_Name,
     1909            "New_Value"=>$Type2_Name);
    27981910    }
    27991911    return %LocalProblems;
    28001912}
    28011913
    2802 sub htmlSpecChars($)
     1914sub specChars($)
    28031915{
    28041916    my $Str = $_[0];
     
    28201932}
    28211933
    2822 sub black_Name($$)
     1934sub blackName($)
     1935{
     1936    my $N = $_[0];
     1937    return "<span class='iname_b'>".$N."</span>";
     1938}
     1939
     1940sub highLight_ItalicColor($$)
    28231941{
    28241942    my ($M, $V) = @_;
    2825     return "<span class='iname_b'>".highLight_Signature($M, $V)."</span>";
    2826 }
    2827 
    2828 sub black_Name_S($)
    2829 {
    2830     my $Name = $_[0];
    2831     $Name=~s!\A(\w+)!<span class='iname_b'>$1</span>&#160;!g;
    2832     return $Name;
    2833 }
    2834 
    2835 sub highLight_Signature($$)
    2836 {
    2837     my ($M, $V) = @_;
    2838     return get_Signature($M, $V, "Class|HTML|Italic");
    2839 }
    2840 
    2841 sub highLight_Signature_Italic_Color($$)
    2842 {
    2843     my ($M, $V) = @_;
    2844     return get_Signature($M, $V, "Full|HTML|Italic|Color");
    2845 }
    2846 
    2847 sub get_Signature($$$)
    2848 {
    2849     my ($Method, $LibVersion, $Kind) = @_;
    2850     if(defined $Cache{"get_Signature"}{$LibVersion}{$Method}{$Kind}) {
    2851         return $Cache{"get_Signature"}{$LibVersion}{$Method}{$Kind};
     1943    return getSignature($M, $V, "Full|HTML|Italic|Color");
     1944}
     1945
     1946sub getSignature($$$)
     1947{
     1948    my ($Method, $LVer, $Kind) = @_;
     1949    if(defined $Cache{"getSignature"}{$LVer}{$Method}{$Kind}) {
     1950        return $Cache{"getSignature"}{$LVer}{$Method}{$Kind};
    28521951    }
    28531952   
    28541953    # settings
    28551954    my ($Full, $Html, $Simple, $Italic, $Color,
    2856     $ShowParams, $ShowClass, $ShowAttr, $Target) = (0, 0, 0, 0, 0, 0, 0, 0, undef);
     1955    $ShowParams, $ShowClass, $ShowAttr, $Desc, $Target) = (0, 0, 0, 0, 0, 0, 0, 0, 0, undef);
    28571956   
    28581957    if($Kind=~/Full/) {
     
    28831982        $ShowAttr = 1;
    28841983    }
    2885    
    2886     if(not defined $MethodInfo{$LibVersion}{$Method}{"ShortName"})
     1984    if($Kind=~/Desc/) {
     1985        $Desc = 1;
     1986    }
     1987   
     1988    if(not defined $MethodInfo{$LVer}{$Method}{"ShortName"})
    28871989    { # from java.lang.Object
    28881990        if($Html or $Simple) {
    2889             return htmlSpecChars($Method);
    2890         }
    2891         else
    2892         {
     1991            return specChars($Method);
     1992        }
     1993        else {
    28931994            return $Method;
    28941995        }
    28951996    }
    28961997   
    2897     my $Signature = $MethodInfo{$LibVersion}{$Method}{"ShortName"};
     1998    my $Signature = $MethodInfo{$LVer}{$Method}{"ShortName"};
    28981999    if($Full or $ShowClass)
    28992000    {
    2900         my $Class = get_TypeName($MethodInfo{$LibVersion}{$Method}{"Class"}, $LibVersion);
    2901        
    2902         if($HideTemplates) {
     2001        my $Class = getTypeName($MethodInfo{$LVer}{$Method}{"Class"}, $LVer);
     2002       
     2003        if($In::Opt{"HideTemplates"}) {
    29032004            $Class=~s/<.*>//g;
    29042005        }
    29052006       
    29062007        if($Html) {
    2907             $Class = htmlSpecChars($Class);
     2008            $Class = specChars($Class);
    29082009        }
    29092010       
     
    29122013    my @Params = ();
    29132014   
    2914     if(defined $MethodInfo{$LibVersion}{$Method}{"Param"})
     2015    if(defined $MethodInfo{$LVer}{$Method}{"Param"})
    29152016    {
    29162017        foreach my $PPos (sort {int($a)<=>int($b)}
    2917         keys(%{$MethodInfo{$LibVersion}{$Method}{"Param"}}))
    2918         {
    2919             my $PTid = $MethodInfo{$LibVersion}{$Method}{"Param"}{$PPos}{"Type"};
    2920             if(my $PTName = get_TypeName($PTid, $LibVersion))
    2921             {
    2922                 if($HideTemplates) {
     2018        keys(%{$MethodInfo{$LVer}{$Method}{"Param"}}))
     2019        {
     2020            my $PTid = $MethodInfo{$LVer}{$Method}{"Param"}{$PPos}{"Type"};
     2021            if(my $PTName = getTypeName($PTid, $LVer))
     2022            {
     2023                if($In::Opt{"HideTemplates"}) {
    29232024                    $PTName=~s/<.*>//g;
    29242025                }
    29252026               
    2926                 if(not $ShowPackages) {
     2027                if(not $In::Opt{"ShowPackages"}) {
    29272028                    $PTName=~s/(\A|\<\s*|\,\s*)[a-z0-9\.]+\./$1/g;
    29282029                }
    29292030               
    29302031                if($Html) {
    2931                     $PTName = htmlSpecChars($PTName);
     2032                    $PTName = specChars($PTName);
    29322033                }
    29332034               
    29342035                if($Full or $ShowParams)
    29352036                {
    2936                     my $PName = $MethodInfo{$LibVersion}{$Method}{"Param"}{$PPos}{"Name"};
     2037                    my $PName = $MethodInfo{$LVer}{$Method}{"Param"}{$PPos}{"Name"};
    29372038                   
    29382039                    if($Simple) {
     
    29712072    {
    29722073        $Signature .= "&#160;";
    2973         $Signature .= "<span class='sym_p'>";
     2074        if($Desc) {
     2075            $Signature .= "<span class='sym_pd'>";
     2076        }
     2077        else {
     2078            $Signature .= "<span class='sym_p'>";
     2079        }
    29742080        if(@Params)
    29752081        {
     
    30132119    if($Full or $ShowAttr)
    30142120    {
    3015         if($MethodInfo{$LibVersion}{$Method}{"Static"}) {
     2121        if($MethodInfo{$LVer}{$Method}{"Static"}) {
    30162122            $Signature .= " [static]";
    30172123        }
    3018         elsif($MethodInfo{$LibVersion}{$Method}{"Abstract"}) {
     2124        elsif($MethodInfo{$LVer}{$Method}{"Abstract"}) {
    30192125            $Signature .= " [abstract]";
    30202126        }
     
    30232129    if($Full)
    30242130    {
    3025         if($ShowAccess)
    3026         {
    3027             if(my $Access = $MethodInfo{$LibVersion}{$Method}{"Access"})
     2131        if($In::Opt{"ShowAccess"})
     2132        {
     2133            if(my $Access = $MethodInfo{$LVer}{$Method}{"Access"})
    30282134            {
    30292135                if($Access ne "public") {
     
    30332139        }
    30342140       
    3035         if(my $ReturnId = $MethodInfo{$LibVersion}{$Method}{"Return"})
    3036         {
    3037             my $RName = get_TypeName($ReturnId, $LibVersion);
     2141        if(my $ReturnId = $MethodInfo{$LVer}{$Method}{"Return"})
     2142        {
     2143            my $RName = getTypeName($ReturnId, $LVer);
    30382144           
    3039             if($HideTemplates) {
     2145            if($In::Opt{"HideTemplates"}) {
    30402146                $RName=~s/<.*>//g;
    30412147            }
    30422148           
    3043             if(not $ShowPackages) {
     2149            if(not $In::Opt{"ShowPackages"}) {
    30442150                $RName=~s/(\A|\<\s*|\,\s*)[a-z0-9\.]+\./$1/g;
    30452151            }
    30462152           
    30472153            if($Simple) {
    3048                 $Signature .= " <b>:</b> ".htmlSpecChars($RName);
     2154                $Signature .= " <b>:</b> ".specChars($RName);
    30492155            }
    30502156            elsif($Html) {
    3051                 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($RName)."</span>";
     2157                $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".specChars($RName)."</span>";
    30522158            }
    30532159            else {
     
    30562162        }
    30572163       
    3058         if(not $SkipDeprecated)
    3059         {
    3060             if($MethodInfo{$LibVersion}{$Method}{"Deprecated"}) {
     2164        if(not $In::Opt{"SkipDeprecated"})
     2165        {
     2166            if($MethodInfo{$LVer}{$Method}{"Deprecated"}) {
    30612167                $Signature .= " *DEPRECATED*";
    30622168            }
     
    30682174    if($Html)
    30692175    {
    3070         if(not $SkipDeprecated) {
     2176        if(not $In::Opt{"SkipDeprecated"}) {
    30712177            $Signature=~s!(\*deprecated\*)!<span class='deprecated'>$1</span>!ig;
    30722178        }
     
    30842190    }
    30852191   
    3086     return ($Cache{"get_Signature"}{$LibVersion}{$Method}{$Kind} = $Signature);
    3087 }
    3088 
    3089 sub checkJavaCompiler($)
    3090 { # check javac: compile simple program
    3091     my $Cmd = $_[0];
    3092    
    3093     if(not $Cmd) {
    3094         return;
    3095     }
    3096    
    3097     writeFile($TMP_DIR."/test_javac/Simple.java",
    3098     "public class Simple {
    3099         public Integer f;
    3100         public void method(Integer p) { };
    3101     }");
    3102     chdir($TMP_DIR."/test_javac");
    3103     system("$Cmd Simple.java 2>errors.txt");
    3104     chdir($ORIG_DIR);
    3105     if($?)
    3106     {
    3107         my $Msg = "something is going wrong with the Java compiler (javac):\n";
    3108         my $Err = readFile($TMP_DIR."/test_javac/errors.txt");
    3109         $Msg .= $Err;
    3110         if($Err=~/elf\/start\.S/ and $Err=~/undefined\s+reference\s+to/)
    3111         { # /usr/lib/gcc/i586-suse-linux/4.5/../../../crt1.o: In function _start:
    3112           # /usr/src/packages/BUILD/glibc-2.11.3/csu/../sysdeps/i386/elf/start.S:115: undefined reference to main
    3113             $Msg .= "\nDid you install a JDK-devel package?";
    3114         }
    3115         exitStatus("Error", $Msg);
    3116     }
    3117 }
    3118 
    3119 sub runTests($$$$)
    3120 {
    3121     my ($TestsPath, $PackageName, $Path_v1, $Path_v2) = @_;
    3122     # compile with old version of package
    3123     my $JavacCmd = get_CmdPath("javac");
    3124     if(not $JavacCmd) {
    3125         exitStatus("Not_Found", "can't find \"javac\" compiler");
    3126     }
    3127     my $JavaCmd = get_CmdPath("java");
    3128     if(not $JavaCmd) {
    3129         exitStatus("Not_Found", "can't find \"java\" command");
    3130     }
    3131     mkpath($TestsPath."/$PackageName/");
    3132     foreach my $ClassPath (cmd_find($Path_v1,"","*\.class",""))
    3133     {# create a compile-time package copy
    3134         copy($ClassPath, $TestsPath."/$PackageName/");
    3135     }
    3136     chdir($TestsPath);
    3137     system($JavacCmd." -g *.java");
    3138     chdir($ORIG_DIR);
    3139     foreach my $TestSrc (cmd_find($TestsPath,"","*\.java",""))
    3140     { # remove test source
    3141         unlink($TestSrc);
    3142     }
    3143    
    3144     my $PkgPath = $TestsPath."/".$PackageName;
    3145     if(-d $PkgPath) {
    3146         rmtree($PkgPath);
    3147     }
    3148     mkpath($PkgPath);
    3149     foreach my $ClassPath (cmd_find($Path_v2,"","*\.class",""))
    3150     {# create a run-time package copy
    3151         copy($ClassPath, $PkgPath."/");
    3152     }
    3153     my $TEST_REPORT = "";
    3154     foreach my $TestPath (cmd_find($TestsPath,"","*\.class",1))
    3155     {# run tests
    3156         my $Name = get_filename($TestPath);
    3157         $Name=~s/\.class\Z//g;
    3158         chdir($TestsPath);
    3159         system($JavaCmd." $Name >result.txt 2>&1");
    3160         chdir($ORIG_DIR);
    3161         my $Result = readFile($TestsPath."/result.txt");
    3162         unlink($TestsPath."/result.txt");
    3163         $TEST_REPORT .= "TEST CASE: $Name\n";
    3164         if($Result) {
    3165             $TEST_REPORT .= "RESULT: FAILED\n";
    3166             $TEST_REPORT .= "OUTPUT:\n$Result\n";
    3167         }
    3168         else {
    3169             $TEST_REPORT .= "RESULT: SUCCESS\n";
    3170         }
    3171         $TEST_REPORT .= "\n";
    3172     }
    3173     writeFile("$TestsPath/Journal.txt", $TEST_REPORT);
    3174    
    3175     if(-d $PkgPath) {
    3176         rmtree($PkgPath);
    3177     }
    3178 }
    3179 
    3180 sub compileJavaLib($$$)
    3181 {
    3182     my ($LibName, $BuildRoot1, $BuildRoot2) = @_;
    3183     my $JavacCmd = get_CmdPath("javac");
    3184     if(not $JavacCmd) {
    3185         exitStatus("Not_Found", "can't find \"javac\" compiler");
    3186     }
    3187     checkJavaCompiler($JavacCmd);
    3188     my $JarCmd = get_CmdPath("jar");
    3189     if(not $JarCmd) {
    3190         exitStatus("Not_Found", "can't find \"jar\" command");
    3191     }
    3192     writeFile("$BuildRoot1/MANIFEST.MF", "Implementation-Version: 1.0\n");
    3193     # space before value, new line
    3194     writeFile("$BuildRoot2/MANIFEST.MF", "Implementation-Version: 2.0\n");
    3195     my (%SrcDir1, %SrcDir2) = ();
    3196     foreach my $Path (cmd_find($BuildRoot1,"f","*.java","")) {
    3197         $SrcDir1{get_dirname($Path)} = 1;
    3198     }
    3199     foreach my $Path (cmd_find($BuildRoot2,"f","*.java","")) {
    3200         $SrcDir2{get_dirname($Path)} = 1;
    3201     }
    3202     # build classes v.1
    3203     foreach my $Dir (keys(%SrcDir1))
    3204     {
    3205         chdir($Dir);
    3206         system("$JavacCmd -g *.java");
    3207         chdir($ORIG_DIR);
    3208         if($?) {
    3209             exitStatus("Error", "can't compile classes v.1");
    3210         }
    3211     }
    3212     # create java archive v.1
    3213     chdir($BuildRoot1);
    3214     system("$JarCmd -cmf MANIFEST.MF $LibName.jar TestPackage");
    3215     chdir($ORIG_DIR);
    3216    
    3217     # build classes v.2
    3218     foreach my $Dir (keys(%SrcDir2))
    3219     {
    3220         chdir($Dir);
    3221         system("$JavacCmd -g *.java");
    3222         chdir($ORIG_DIR);
    3223         if($?) {
    3224             exitStatus("Error", "can't compile classes v.2");
    3225         }
    3226     }
    3227     # create java archive v.2
    3228     chdir($BuildRoot2);
    3229     system("$JarCmd -cmf MANIFEST.MF $LibName.jar TestPackage");
    3230     chdir($ORIG_DIR);
    3231    
    3232     foreach my $SrcPath (cmd_find($BuildRoot1,"","*\.java","")) {
    3233         unlink($SrcPath);
    3234     }
    3235     foreach my $SrcPath (cmd_find($BuildRoot2,"","*\.java","")) {
    3236         unlink($SrcPath);
    3237     }
    3238     return 1;
    3239 }
    3240 
    3241 sub readLineNum($$)
    3242 {
    3243     my ($Path, $Num) = @_;
    3244     return "" if(not $Path or not -f $Path);
    3245     open (FILE, $Path);
    3246     foreach (1 ... $Num) {
    3247         <FILE>;
    3248     }
    3249     my $Line = <FILE>;
    3250     close(FILE);
    3251     return $Line;
    3252 }
    3253 
    3254 sub readAttributes($$)
    3255 {
    3256     my ($Path, $Num) = @_;
    3257     return () if(not $Path or not -f $Path);
    3258     my %Attributes = ();
    3259     if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
    3260     {
    3261         foreach my $AttrVal (split(/;/, $1))
    3262         {
    3263             if($AttrVal=~/(.+):(.+)/)
    3264             {
    3265                 my ($Name, $Value) = ($1, $2);
    3266                 $Attributes{$Name} = $Value;
    3267             }
    3268         }
    3269     }
    3270     return \%Attributes;
    3271 }
    3272 
    3273 sub runChecker($$$)
    3274 {
    3275     my ($LibName, $Path1, $Path2) = @_;
    3276     writeFile("$LibName/v1.xml", "
    3277         <version>
    3278             1.0
    3279         </version>
    3280         <archives>
    3281             ".get_abs_path($Path1)."
    3282         </archives>");
    3283     writeFile("$LibName/v2.xml", "
    3284         <version>
    3285             2.0
    3286         </version>
    3287         <archives>
    3288             ".get_abs_path($Path2)."
    3289         </archives>");
    3290     my $Cmd = "perl $0 -l $LibName $LibName/v1.xml $LibName/v2.xml";
    3291     if($Quick) {
    3292         $Cmd .= " -quick";
    3293     }
    3294     if(defined $SkipDeprecated) {
    3295         $Cmd .= " -skip-deprecated";
    3296     }
    3297     if(defined $OldStyle) {
    3298         $Cmd .= " -old-style";
    3299     }
    3300     writeFile($TMP_DIR."/skip-annotations.list", "TestPackage.Beta");
    3301     $Cmd .= " -skip-annotations-list ".$TMP_DIR."/skip-annotations.list";
    3302     if($Debug)
    3303     {
    3304         $Cmd .= " -debug";
    3305         printMsg("INFO", "running $Cmd");
    3306     }
    3307     system($Cmd);
    3308     my $Report = "compat_reports/$LibName/1.0_to_2.0/compat_report.html";
    3309     # Binary
    3310     my $BReport = readAttributes($Report, 0);
    3311     my $NProblems = $BReport->{"type_problems_high"}+$BReport->{"type_problems_medium"};
    3312     $NProblems += $BReport->{"method_problems_high"}+$BReport->{"method_problems_medium"};
    3313     $NProblems += $BReport->{"removed"};
    3314     # Source
    3315     my $SReport = readAttributes($Report, 1);
    3316     $NProblems += $SReport->{"type_problems_high"}+$SReport->{"type_problems_medium"};
    3317     $NProblems += $SReport->{"method_problems_high"}+$SReport->{"method_problems_medium"};
    3318     $NProblems += $SReport->{"removed"};
    3319     if($NProblems>=100) {
    3320         printMsg("INFO", "test result: SUCCESS ($NProblems breaks found)\n");
    3321     }
    3322     else {
    3323         printMsg("ERROR", "test result: FAILED ($NProblems breaks found)\n");
    3324     }
    3325 }
    3326 
    3327 sub writeFile($$)
    3328 {
    3329     my ($Path, $Content) = @_;
    3330     return if(not $Path);
    3331     if(my $Dir = get_dirname($Path)) {
    3332         mkpath($Dir);
    3333     }
    3334     open (FILE, ">".$Path) || die ("can't open file \'$Path\': $!\n");
    3335     print FILE $Content;
    3336     close(FILE);
    3337 }
    3338 
    3339 sub readFile($)
    3340 {
    3341     my $Path = $_[0];
    3342     return "" if(not $Path or not -f $Path);
    3343     open (FILE, $Path);
    3344     my $Content = join("", <FILE>);
    3345     close(FILE);
    3346     $Content=~s/\r//g;
    3347     return $Content;
    3348 }
    3349 
    3350 sub appendFile($$)
    3351 {
    3352     my ($Path, $Content) = @_;
    3353     return if(not $Path);
    3354     if(my $Dir = get_dirname($Path)) {
    3355         mkpath($Dir);
    3356     }
    3357     open(FILE, ">>".$Path) || die ("can't open file \'$Path\': $!\n");
    3358     print FILE $Content;
    3359     close(FILE);
    3360 }
    3361 
    3362 sub get_Report_Header($)
     2192    return ($Cache{"getSignature"}{$LVer}{$Method}{$Kind} = $Signature);
     2193}
     2194
     2195sub getReportHeader($)
    33632196{
    33642197    my $Level = $_[0];
     
    33732206        $Report_Header .= "API compatibility";
    33742207    }
    3375     $Report_Header .= " report for the <span style='color:Blue;'>$TargetTitle</span> library between <span style='color:Red;'>".$Descriptor{1}{"Version"}."</span> and <span style='color:Red;'>".$Descriptor{2}{"Version"}."</span> versions";
    3376     if($ClientPath) {
    3377         $Report_Header .= " (concerning portability of the client: <span style='color:Blue;'>".get_filename($ClientPath)."</span>)";
     2208    $Report_Header .= " report for the <span style='color:Blue;'>".$In::Opt{"TargetTitle"}."</span> library between <span style='color:Red;'>".$In::Desc{1}{"Version"}."</span> and <span style='color:Red;'>".$In::Desc{2}{"Version"}."</span> versions";
     2209    if($In::Opt{"ClientPath"}) {
     2210        $Report_Header .= " (concerning portability of the client: <span style='color:Blue;'>".getFilename($In::Opt{"ClientPath"})."</span>)";
    33782211    }
    33792212    $Report_Header .= "</h1>\n";
     
    33812214}
    33822215
    3383 sub get_SourceInfo()
     2216sub getSourceInfo()
    33842217{
    33852218    my $CheckedArchives = "<a name='Checked_Archives'></a>";
    3386     if($OldStyle) {
    3387         $CheckedArchives .= "<h2>Java ARchives (".keys(%{$LibArchives{1}}).")</h2>";
     2219    if($In::Opt{"OldStyle"}) {
     2220        $CheckedArchives .= "<h2>Java Archives (".keys(%{$LibArchives{1}}).")</h2>";
    33882221    }
    33892222    else {
    3390         $CheckedArchives .= "<h2>Java ARchives <span class='gray'>&nbsp;".keys(%{$LibArchives{1}})."&nbsp;</span></h2>";
     2223        $CheckedArchives .= "<h2>Java Archives <span class='gray'>&nbsp;".keys(%{$LibArchives{1}})."&nbsp;</span></h2>";
    33912224    }
    33922225    $CheckedArchives .= "\n<hr/><div class='jar_list'>\n";
    33932226    foreach my $ArchivePath (sort {lc($a) cmp lc($b)}  keys(%{$LibArchives{1}})) {
    3394         $CheckedArchives .= get_filename($ArchivePath)."<br/>\n";
     2227        $CheckedArchives .= getFilename($ArchivePath)."<br/>\n";
    33952228    }
    33962229    $CheckedArchives .= "</div><br/>$TOP_REF<br/>\n";
     
    33982231}
    33992232
    3400 sub get_TypeProblems_Count($$)
     2233sub getTypeProblemsCount($$)
    34012234{
    34022235    my ($TargetSeverity, $Level) = @_;
     
    34082241        foreach my $Kind (sort keys(%{$TypeChanges{$Level}{$Type_Name}}))
    34092242        {
    3410             if($TypeProblems_Kind{$Level}{$Kind} ne $TargetSeverity) {
     2243            if($CompatRules{$Level}{$Kind}{"Severity"} ne $TargetSeverity) {
    34112244                next;
    34122245            }
     2246           
    34132247            foreach my $Location (sort keys(%{$TypeChanges{$Level}{$Type_Name}{$Kind}}))
    34142248            {
     
    34282262}
    34292263
    3430 sub show_number($)
     2264sub showNum($)
    34312265{
    34322266    if($_[0])
    34332267    {
    3434         my $Num = cut_off_number($_[0], 2, 0);
     2268        my $Num = cutNum($_[0], 2, 0);
    34352269        if($Num eq "0")
    34362270        {
    34372271            foreach my $P (3 .. 7)
    34382272            {
    3439                 $Num = cut_off_number($_[0], $P, 1);
     2273                $Num = cutNum($_[0], $P, 1);
    34402274                if($Num ne "0") {
    34412275                    last;
     
    34512285}
    34522286
    3453 sub cut_off_number($$$)
     2287sub cutNum($$$)
    34542288{
    34552289    my ($num, $digs_to_cut, $z) = @_;
     
    34772311}
    34782312
    3479 sub get_Summary($)
     2313sub getSummary($)
    34802314{
    34812315    my $Level = $_[0];
    34822316    my ($Added, $Removed, $M_Problems_High, $M_Problems_Medium, $M_Problems_Low,
    3483     $T_Problems_High, $T_Problems_Medium, $T_Problems_Low, $M_Other, $T_Other) = (0,0,0,0,0,0,0,0,0,0);
     2317    $T_Problems_High, $T_Problems_Medium, $T_Problems_Low, $M_Other, $T_Other) = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
    34842318   
    34852319    %{$RESULT{$Level}} = (
    34862320        "Problems"=>0,
    34872321        "Warnings"=>0,
    3488         "Affected"=>0 );
     2322        "Affected"=>0);
    34892323   
    34902324    foreach my $Method (sort keys(%CompatProblems))
     
    34922326        foreach my $Kind (sort keys(%{$CompatProblems{$Method}}))
    34932327        {
    3494             if(my $Severity = $MethodProblems_Kind{$Level}{$Kind})
    3495             {
    3496                 foreach my $Location (sort keys(%{$CompatProblems{$Method}{$Kind}}))
     2328            if($CompatRules{$Level}{$Kind}{"Kind"} eq "Methods")
     2329            {
     2330                my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
     2331                foreach my $Loc (sort keys(%{$CompatProblems{$Method}{$Kind}}))
    34972332                {
    34982333                    if($Kind eq "Added_Method")
     
    35312366                            $M_Problems_Low+=1;
    35322367                        }
    3533                         if(($Severity ne "Low" or $StrictCompat)
     2368                        if(($Severity ne "Low" or $In::Opt{"StrictCompat"})
    35342369                        and $Severity ne "Safe") {
    35352370                            $TotalAffected{$Level}{$Method} = $Severity;
     
    35452380    foreach my $Method (sort keys(%CompatProblems))
    35462381    {
    3547         my @Kinds = sort keys(%{$CompatProblems{$Method}});
    3548         foreach my $Kind (@Kinds)
    3549         {
    3550             if(my $Severity = $TypeProblems_Kind{$Level}{$Kind})
    3551             {
    3552                 my @Locs = sort {length($a)<=>length($b)} sort keys(%{$CompatProblems{$Method}{$Kind}});
    3553                 foreach my $Location (@Locs)
     2382        foreach my $Kind (sort keys(%{$CompatProblems{$Method}}))
     2383        {
     2384            if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
     2385            {
     2386                my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
     2387                if(($Severity ne "Low" or $In::Opt{"StrictCompat"})
     2388                and $Severity ne "Safe")
    35542389                {
    3555                     my $Type_Name = $CompatProblems{$Method}{$Kind}{$Location}{"Type_Name"};
    3556                     my $Target = $CompatProblems{$Method}{$Kind}{$Location}{"Target"};
     2390                    if(my $Sev = $TotalAffected{$Level}{$Method})
     2391                    {
     2392                        if($Severity_Val{$Severity}>$Severity_Val{$Sev}) {
     2393                            $TotalAffected{$Level}{$Method} = $Severity;
     2394                        }
     2395                    }
     2396                    else {
     2397                        $TotalAffected{$Level}{$Method} = $Severity;
     2398                    }
     2399                }
     2400               
     2401                my $MK = $CompatProblems{$Method}{$Kind};
     2402                my (@Locs1, @Locs2) = ();
     2403                foreach my $Loc (sort {length($a)<=>length($b)} sort keys(%{$MK}))
     2404                {
     2405                    if(index($Loc, "retval")==0 or index($Loc, "this")==0) {
     2406                        push(@Locs2, $Loc);
     2407                    }
     2408                    else {
     2409                        push(@Locs1, $Loc);
     2410                    }
     2411                }
     2412                foreach my $Loc (@Locs1, @Locs2)
     2413                {
     2414                    my $Type = $MK->{$Loc}{"Type_Name"};
     2415                    my $Target = $MK->{$Loc}{"Target"};
    35572416                   
    3558                     if(defined $MethodTypeIndex{$Method}{$Type_Name}{$Kind}{$Target})
     2417                    if(defined $MethodTypeIndex{$Method}{$Type}{$Kind}{$Target})
    35592418                    { # one location for one type and target
    35602419                        next;
    35612420                    }
    3562                     $MethodTypeIndex{$Method}{$Type_Name}{$Kind}{$Target} = 1;
    3563                     $TypeChanges{$Level}{$Type_Name}{$Kind}{$Location} = $CompatProblems{$Method}{$Kind}{$Location};
     2421                    $MethodTypeIndex{$Method}{$Type}{$Kind}{$Target} = 1;
    35642422                   
    3565                     if(($Severity ne "Low" or $StrictCompat)
    3566                     and $Severity ne "Safe")
    3567                     {
    3568                         if(my $Sev = $TotalAffected{$Level}{$Method})
    3569                         {
    3570                             if($Severity_Val{$Severity}>$Severity_Val{$Sev}) {
    3571                                 $TotalAffected{$Level}{$Method} = $Severity;
    3572                             }
    3573                         }
    3574                         else {
    3575                             $TotalAffected{$Level}{$Method} = $Severity;
    3576                         }
    3577                     }
     2423                    $TypeChanges{$Level}{$Type}{$Kind}{$Loc} = $MK->{$Loc};
     2424                    $TypeProblemsIndex{$Level}{$Type}{$Kind}{$Loc}{$Method} = 1;
    35782425                }
    35792426            }
     
    35832430    %MethodTypeIndex = (); # clear memory
    35842431   
    3585    
    3586     $T_Problems_High = get_TypeProblems_Count("High", $Level);
    3587     $T_Problems_Medium = get_TypeProblems_Count("Medium", $Level);
    3588     $T_Problems_Low = get_TypeProblems_Count("Low", $Level);
    3589     $T_Other = get_TypeProblems_Count("Safe", $Level);
     2432    $T_Problems_High = getTypeProblemsCount("High", $Level);
     2433    $T_Problems_Medium = getTypeProblemsCount("Medium", $Level);
     2434    $T_Problems_Low = getTypeProblemsCount("Low", $Level);
     2435    $T_Other = getTypeProblemsCount("Safe", $Level);
    35902436   
    35912437    my $SCount = keys(%CheckedMethods)-$Added;
     
    36052451        $RESULT{$Level}{"Affected"} = 0;
    36062452    }
    3607     $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
     2453    $RESULT{$Level}{"Affected"} = showNum($RESULT{$Level}{"Affected"});
    36082454    if($RESULT{$Level}{"Affected"}>=100) {
    36092455        $RESULT{$Level}{"Affected"} = 100;
     
    36152461    $TestInfo .= "<h2>Test Info</h2><hr/>\n";
    36162462    $TestInfo .= "<table class='summary'>\n";
    3617     $TestInfo .= "<tr><th>Library Name</th><td>$TargetTitle</td></tr>\n";
    3618     $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}."</td></tr>\n";
    3619     $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}."</td></tr>\n";
    3620    
    3621     if($JoinReport)
     2463    $TestInfo .= "<tr><th>Library Name</th><td>".$In::Opt{"TargetTitle"}."</td></tr>\n";
     2464    $TestInfo .= "<tr><th>Version #1</th><td>".$In::Desc{1}{"Version"}."</td></tr>\n";
     2465    $TestInfo .= "<tr><th>Version #2</th><td>".$In::Desc{2}{"Version"}."</td></tr>\n";
     2466   
     2467    if($In::Opt{"JoinReport"})
    36222468    {
    36232469        if($Level eq "Binary") {
     
    36312477   
    36322478    # test results
    3633     $TestResults .= "<h2>Test Results</h2><hr/>";
    3634     $TestResults .= "<table class='summary'>";
     2479    $TestResults .= "<h2>Test Results</h2><hr/>\n";
     2480    $TestResults .= "<table class='summary'>\n";
    36352481   
    36362482    my $Checked_Archives_Link = "0";
     
    36412487   
    36422488    $RESULT{$Level}{"Problems"} += $Removed+$M_Problems_High+$T_Problems_High+$T_Problems_Medium+$M_Problems_Medium;
    3643     if($StrictCompat) {
     2489    if($In::Opt{"StrictCompat"}) {
    36442490        $RESULT{$Level}{"Problems"}+=$T_Problems_Low+$M_Problems_Low;
    36452491    }
     
    36522498    $TestResults .= "<tr><th>Compatibility</th>\n";
    36532499   
    3654     my $BC_Rate = show_number(100 - $RESULT{$Level}{"Affected"});
     2500    my $BC_Rate = showNum(100 - $RESULT{$Level}{"Affected"});
    36552501   
    36562502    if($RESULT{$Level}{"Problems"})
     
    36772523   
    36782524    # Problem Summary
    3679     $Problem_Summary .= "<h2>Problem Summary</h2><hr/>";
    3680     $Problem_Summary .= "<table class='summary'>";
    3681     $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
     2525    $Problem_Summary .= "<h2>Problem Summary</h2><hr/>\n";
     2526    $Problem_Summary .= "<table class='summary'>\n";
     2527    $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>\n";
    36822528   
    36832529    my $Added_Link = "0";
    36842530    if($Added>0)
    36852531    {
    3686         if($ShortMode) {
     2532        if($In::Opt{"ShortMode"}) {
    36872533            $Added_Link = $Added;
    36882534        }
    36892535        else
    36902536        {
    3691             if($JoinReport) {
     2537            if($In::Opt{"JoinReport"}) {
    36922538                $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
    36932539            }
     
    36982544    }
    36992545    $META_DATA .= "added:$Added;";
    3700     $Problem_Summary .= "<tr><th>Added Methods</th><td>-</td><td".getStyle("M", "Added", $Added).">$Added_Link</td></tr>";
     2546    $Problem_Summary .= "<tr><th>Added Methods</th><td>-</td><td".getStyle("M", "Added", $Added).">$Added_Link</td></tr>\n";
    37012547   
    37022548    my $Removed_Link = "0";
    37032549    if($Removed>0)
    37042550    {
    3705         if($ShortMode) {
     2551        if($In::Opt{"ShortMode"}) {
    37062552            $Removed_Link = $Removed;
    37072553        }
    37082554        else
    37092555        {
    3710             if($JoinReport) {
     2556            if($In::Opt{"JoinReport"}) {
    37112557                $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
    37122558            }
     
    37182564    $META_DATA .= "removed:$Removed;";
    37192565    $Problem_Summary .= "<tr><th>Removed Methods</th>";
    3720     $Problem_Summary .= "<td>High</td><td".getStyle("M", "Removed", $Removed).">$Removed_Link</td></tr>";
     2566    $Problem_Summary .= "<td>High</td><td".getStyle("M", "Removed", $Removed).">$Removed_Link</td></tr>\n";
    37212567   
    37222568    my $TH_Link = "0";
    3723     $TH_Link = "<a href='#".get_Anchor("Type", $Level, "High")."' style='color:Blue;'>$T_Problems_High</a>" if($T_Problems_High>0);
     2569    $TH_Link = "<a href='#".getAnchor("Type", $Level, "High")."' style='color:Blue;'>$T_Problems_High</a>" if($T_Problems_High>0);
    37242570    $META_DATA .= "type_problems_high:$T_Problems_High;";
    37252571    $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
    3726     $Problem_Summary .= "<td>High</td><td".getStyle("T", "High", $T_Problems_High).">$TH_Link</td></tr>";
     2572    $Problem_Summary .= "<td>High</td><td".getStyle("T", "High", $T_Problems_High).">$TH_Link</td></tr>\n";
    37272573   
    37282574    my $TM_Link = "0";
    3729     $TM_Link = "<a href='#".get_Anchor("Type", $Level, "Medium")."' style='color:Blue;'>$T_Problems_Medium</a>" if($T_Problems_Medium>0);
     2575    $TM_Link = "<a href='#".getAnchor("Type", $Level, "Medium")."' style='color:Blue;'>$T_Problems_Medium</a>" if($T_Problems_Medium>0);
    37302576    $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
    3731     $Problem_Summary .= "<tr><td>Medium</td><td".getStyle("T", "Medium", $T_Problems_Medium).">$TM_Link</td></tr>";
     2577    $Problem_Summary .= "<tr><td>Medium</td><td".getStyle("T", "Medium", $T_Problems_Medium).">$TM_Link</td></tr>\n";
    37322578   
    37332579    my $TL_Link = "0";
    3734     $TL_Link = "<a href='#".get_Anchor("Type", $Level, "Low")."' style='color:Blue;'>$T_Problems_Low</a>" if($T_Problems_Low>0);
     2580    $TL_Link = "<a href='#".getAnchor("Type", $Level, "Low")."' style='color:Blue;'>$T_Problems_Low</a>" if($T_Problems_Low>0);
    37352581    $META_DATA .= "type_problems_low:$T_Problems_Low;";
    3736     $Problem_Summary .= "<tr><td>Low</td><td".getStyle("T", "Low", $T_Problems_Low).">$TL_Link</td></tr>";
     2582    $Problem_Summary .= "<tr><td>Low</td><td".getStyle("T", "Low", $T_Problems_Low).">$TL_Link</td></tr>\n";
    37372583   
    37382584    my $MH_Link = "0";
    3739     $MH_Link = "<a href='#".get_Anchor("Method", $Level, "High")."' style='color:Blue;'>$M_Problems_High</a>" if($M_Problems_High>0);
     2585    $MH_Link = "<a href='#".getAnchor("Method", $Level, "High")."' style='color:Blue;'>$M_Problems_High</a>" if($M_Problems_High>0);
    37402586    $META_DATA .= "method_problems_high:$M_Problems_High;";
    37412587    $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Methods</th>";
    3742     $Problem_Summary .= "<td>High</td><td".getStyle("M", "High", $M_Problems_High).">$MH_Link</td></tr>";
     2588    $Problem_Summary .= "<td>High</td><td".getStyle("M", "High", $M_Problems_High).">$MH_Link</td></tr>\n";
    37432589   
    37442590    my $MM_Link = "0";
    3745     $MM_Link = "<a href='#".get_Anchor("Method", $Level, "Medium")."' style='color:Blue;'>$M_Problems_Medium</a>" if($M_Problems_Medium>0);
     2591    $MM_Link = "<a href='#".getAnchor("Method", $Level, "Medium")."' style='color:Blue;'>$M_Problems_Medium</a>" if($M_Problems_Medium>0);
    37462592    $META_DATA .= "method_problems_medium:$M_Problems_Medium;";
    3747     $Problem_Summary .= "<tr><td>Medium</td><td".getStyle("M", "Medium", $M_Problems_Medium).">$MM_Link</td></tr>";
     2593    $Problem_Summary .= "<tr><td>Medium</td><td".getStyle("M", "Medium", $M_Problems_Medium).">$MM_Link</td></tr>\n";
    37482594   
    37492595    my $ML_Link = "0";
    3750     $ML_Link = "<a href='#".get_Anchor("Method", $Level, "Low")."' style='color:Blue;'>$M_Problems_Low</a>" if($M_Problems_Low>0);
     2596    $ML_Link = "<a href='#".getAnchor("Method", $Level, "Low")."' style='color:Blue;'>$M_Problems_Low</a>" if($M_Problems_Low>0);
    37512597    $META_DATA .= "method_problems_low:$M_Problems_Low;";
    3752     $Problem_Summary .= "<tr><td>Low</td><td".getStyle("M", "Low", $M_Problems_Low).">$ML_Link</td></tr>";
     2598    $Problem_Summary .= "<tr><td>Low</td><td".getStyle("M", "Low", $M_Problems_Low).">$ML_Link</td></tr>\n";
    37532599   
    37542600    # Safe Changes
    37552601    if($T_Other)
    37562602    {
    3757         my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
     2603        my $TS_Link = "<a href='#".getAnchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
    37582604        $Problem_Summary .= "<tr><th>Other Changes<br/>in Data Types</th><td>-</td><td".getStyle("T", "Safe", $T_Other).">$TS_Link</td></tr>\n";
    37592605    }
     
    37612607    if($M_Other)
    37622608    {
    3763         my $MS_Link = "<a href='#".get_Anchor("Method", $Level, "Safe")."' style='color:Blue;'>$M_Other</a>";
     2609        my $MS_Link = "<a href='#".getAnchor("Method", $Level, "Safe")."' style='color:Blue;'>$M_Other</a>";
    37642610        $Problem_Summary .= "<tr><th>Other Changes<br/>in Methods</th><td>-</td><td".getStyle("M", "Safe", $M_Other).">$MS_Link</td></tr>\n";
    37652611    }
     
    37902636}
    37912637
    3792 sub get_Anchor($$$)
     2638sub getAnchor($$$)
    37932639{
    37942640    my ($Kind, $Level, $Severity) = @_;
    3795     if($JoinReport)
     2641    if($In::Opt{"JoinReport"})
    37962642    {
    37972643        if($Severity eq "Safe") {
     
    38132659}
    38142660
    3815 sub get_Report_Added($)
    3816 {
    3817     if($ShortMode) {
     2661sub getReportAdded($)
     2662{
     2663    if($In::Opt{"ShortMode"}) {
    38182664        return "";
    38192665    }
     
    38282674            {
    38292675                my $ArchiveName = $MethodInfo{2}{$Method}{"Archive"};
    3830                 my $ClassName = get_ShortName($MethodInfo{2}{$Method}{"Class"}, 2);
     2676                my $ClassName = getShortName($MethodInfo{2}{$Method}{"Class"}, 2);
    38312677                if($Level eq "Source")
    38322678                {
     
    38542700            foreach my $NameSpace (sort keys(%NameSpace_Method))
    38552701            {
    3856                 $ADDED_METHODS .= "<span class='jar'>$ArchiveName</span>, <span class='cname'>".htmlSpecChars($ShowClass).".class</span><br/>\n";
     2702                $ADDED_METHODS .= "<span class='jar'>$ArchiveName</span>, <span class='cname'>".specChars($ShowClass).".class</span><br/>\n";
    38572703               
    38582704                if($NameSpace) {
     
    38602706                }
    38612707               
    3862                 if($Compact) {
     2708                if($In::Opt{"Compact"}) {
    38632709                    $ADDED_METHODS .= "<div class='symbols'>";
    38642710                }
     
    38712717                    my $Signature = undef;
    38722718                   
    3873                     if($Compact) {
    3874                         $Signature = get_Signature($Method, 2, "Full|HTML|Simple");
     2719                    if($In::Opt{"Compact"}) {
     2720                        $Signature = getSignature($Method, 2, "Full|HTML|Simple");
    38752721                    }
    38762722                    else {
    3877                         $Signature = highLight_Signature_Italic_Color($Method, 2);
     2723                        $Signature = highLight_ItalicColor($Method, 2);
    38782724                    }
    38792725                   
     
    38822728                    }
    38832729                   
    3884                     if($Compact) {
     2730                    if($In::Opt{"Compact"}) {
    38852731                        $ADDED_METHODS .= "&nbsp;".$Signature."<br/>\n";
    38862732                    }
    38872733                    else {
    3888                         $ADDED_METHODS .= insertIDs($ContentSpanStart.$Signature.$ContentSpanEnd."<br/>\n".$ContentDivStart."<span class='mngl'>[mangled: <b>".htmlSpecChars($Method)."</b>]</span><br/><br/>".$ContentDivEnd."\n");
     2734                        $ADDED_METHODS .= insertIDs($ContentSpanStart.$Signature.$ContentSpanEnd."<br/>\n".$ContentDivStart."<span class='mngl'>".specChars($Method)."</span><br/><br/>".$ContentDivEnd."\n");
    38892735                    }
    38902736                }
    38912737               
    3892                 if($Compact) {
     2738                if($In::Opt{"Compact"}) {
    38932739                    $ADDED_METHODS .= "</div>";
    38942740                }
     
    39022748    {
    39032749        my $Anchor = "<a name='Added'></a>";
    3904         if($JoinReport) {
     2750        if($In::Opt{"JoinReport"}) {
    39052751            $Anchor = "<a name='".$Level."_Added'></a>";
    39062752        }
    3907         if($OldStyle) {
     2753        if($In::Opt{"OldStyle"}) {
    39082754            $ADDED_METHODS = "<h2>Added Methods ($Added_Number)</h2><hr/>\n".$ADDED_METHODS;
    39092755        }
     
    39162762}
    39172763
    3918 sub get_Report_Removed($)
    3919 {
    3920     if($ShortMode) {
     2764sub getReportRemoved($)
     2765{
     2766    if($In::Opt{"ShortMode"}) {
    39212767        return "";
    39222768    }
     
    39372783                }
    39382784                my $ArchiveName = $MethodInfo{1}{$Method}{"Archive"};
    3939                 my $ClassName = get_ShortName($MethodInfo{1}{$Method}{"Class"}, 1);
     2785                my $ClassName = getShortName($MethodInfo{1}{$Method}{"Class"}, 1);
    39402786                $MethodRemovedFromArchiveClass{$ArchiveName}{$ClassName}{$Method} = 1;
    39412787            }
     
    39582804            foreach my $NameSpace (sort keys(%NameSpace_Method))
    39592805            {
    3960                 $REMOVED_METHODS .= "<span class='jar'>$ArchiveName</span>, <span class='cname'>".htmlSpecChars($ShowClass).".class</span><br/>\n";
     2806                $REMOVED_METHODS .= "<span class='jar'>$ArchiveName</span>, <span class='cname'>".specChars($ShowClass).".class</span><br/>\n";
    39612807               
    39622808                if($NameSpace) {
     
    39642810                }
    39652811               
    3966                 if($Compact) {
     2812                if($In::Opt{"Compact"}) {
    39672813                    $REMOVED_METHODS .= "<div class='symbols'>";
    39682814                }
     
    39752821                    my $Signature = undef;
    39762822                   
    3977                     if($Compact) {
    3978                         $Signature = get_Signature($Method, 1, "Full|HTML|Simple");
     2823                    if($In::Opt{"Compact"}) {
     2824                        $Signature = getSignature($Method, 1, "Full|HTML|Simple");
    39792825                    }
    39802826                    else {
    3981                         $Signature = highLight_Signature_Italic_Color($Method, 1);
     2827                        $Signature = highLight_ItalicColor($Method, 1);
    39822828                    }
    39832829                   
     
    39862832                    }
    39872833                   
    3988                     if($Compact) {
     2834                    if($In::Opt{"Compact"}) {
    39892835                        $REMOVED_METHODS .= "&nbsp;".$Signature."<br/>\n";
    39902836                    }
    39912837                    else {
    3992                         $REMOVED_METHODS .= insertIDs($ContentSpanStart.$Signature.$ContentSpanEnd."<br/>\n".$ContentDivStart."<span class='mngl'>[mangled: <b>".htmlSpecChars($Method)."</b>]</span><br/><br/>".$ContentDivEnd."\n");
     2838                        $REMOVED_METHODS .= insertIDs($ContentSpanStart.$Signature.$ContentSpanEnd."<br/>\n".$ContentDivStart."<span class='mngl'>".specChars($Method)."</span><br/><br/>".$ContentDivEnd."\n");
    39932839                    }
    39942840                }
    39952841               
    3996                 if($Compact) {
     2842                if($In::Opt{"Compact"}) {
    39972843                    $REMOVED_METHODS .= "</div>";
    39982844                }
     
    40052851    {
    40062852        my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
    4007         if($JoinReport) {
     2853        if($In::Opt{"JoinReport"}) {
    40082854            $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
    40092855        }
    4010         if($OldStyle) {
     2856        if($In::Opt{"OldStyle"}) {
    40112857            $REMOVED_METHODS = "<h2>Removed Methods ($Removed_Number)</h2><hr/>\n".$REMOVED_METHODS;
    40122858        }
     
    40192865}
    40202866
    4021 sub get_Report_MethodProblems($$)
     2867sub readRules($)
     2868{
     2869    my $Kind = $_[0];
     2870    if(not -f $RULES_PATH{$Kind}) {
     2871        exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
     2872    }
     2873    my $Content = readFile($RULES_PATH{$Kind});
     2874    while(my $Rule = parseTag(\$Content, "rule"))
     2875    {
     2876        my $RId = parseTag(\$Rule, "id");
     2877        my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
     2878        foreach my $Prop (@Properties) {
     2879            if(my $Value = parseTag(\$Rule, lc($Prop)))
     2880            {
     2881                $Value=~s/\n[ ]*//;
     2882                $CompatRules{$Kind}{$RId}{$Prop} = $Value;
     2883            }
     2884        }
     2885        if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Methods|Parameters)\Z/) {
     2886            $CompatRules{$Kind}{$RId}{"Kind"} = "Methods";
     2887        }
     2888        else { # Types, Fields
     2889            $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
     2890        }
     2891    }
     2892}
     2893
     2894sub addMarkup($)
     2895{
     2896    my $Content = $_[0];
     2897   
     2898    # auto-markup
     2899    $Content=~s/\n[ ]*//; # spaces
     2900    $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
     2901    if($Content=~/\ANOTE:/)
     2902    { # notes
     2903        $Content=~s!(NOTE):!<b>$1</b>:!g;
     2904    }
     2905    else {
     2906        $Content=~s!(NOTE):!<br/><br/><b>$1</b>:!g;
     2907    }
     2908   
     2909    my @Keywords = (
     2910        "static",
     2911        "abstract",
     2912        "default",
     2913        "final",
     2914        "synchronized"
     2915    );
     2916   
     2917    my $MKeys = join("|", @Keywords);
     2918    foreach (@Keywords) {
     2919        $MKeys .= "|non-".$_;
     2920    }
     2921   
     2922    $Content=~s!(became\s*)($MKeys)([^\w-]|\Z)!$1<b>$2</b>$3!ig; # intrinsic types, modifiers
     2923   
     2924    # Markdown
     2925    $Content=~s!\*\*([\w\-\@]+)\*\*!<b>$1</b>!ig;
     2926    $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
     2927   
     2928    return $Content;
     2929}
     2930
     2931sub applyMacroses($$$$$)
     2932{
     2933    my ($Level, $Kind, $Content, $Problem, $AddAttr) = @_;
     2934   
     2935    $Content = addMarkup($Content);
     2936   
     2937    # macros
     2938    foreach my $Attr (sort {$b cmp $a} (keys(%{$Problem}), keys(%{$AddAttr})))
     2939    {
     2940        my $Macro = "\@".lc($Attr);
     2941        my $Value = undef;
     2942       
     2943        if(defined $Problem->{$Attr}) {
     2944            $Value = $Problem->{$Attr};
     2945        }
     2946        else {
     2947            $Value = $AddAttr->{$Attr};
     2948        }
     2949       
     2950        if(not defined $Value
     2951        or $Value eq "") {
     2952            next;
     2953        }
     2954       
     2955        if(index($Content, $Macro)==-1) {
     2956            next;
     2957        }
     2958       
     2959        if($Attr eq "Param_Pos") {
     2960            $Value = showPos($Value);
     2961        }
     2962       
     2963        if($Attr eq "Invoked") {
     2964            $Value = blackName(specChars($Value));
     2965        }
     2966        elsif($Value=~/\s/) {
     2967            $Value = "<span class='value'>".specChars($Value)."</span>";
     2968        }
     2969        else
     2970        {
     2971            my $Fmt = "Class|HTML|Desc";
     2972           
     2973            if($Attr ne "Invoked_By")
     2974            {
     2975                if($Attr eq "Method_Short"
     2976                or $Kind!~/Overridden|Moved_Up/) {
     2977                    $Fmt = "HTML|Desc";
     2978                }
     2979            }
     2980           
     2981            if(defined $MethodInfo{1}{$Value}
     2982            and defined $MethodInfo{1}{$Value}{"ShortName"}) {
     2983                $Value = blackName(getSignature($Value, 1, $Fmt));
     2984            }
     2985            elsif(defined $MethodInfo{2}{$Value}
     2986            and defined $MethodInfo{2}{$Value}{"ShortName"}) {
     2987                $Value = blackName(getSignature($Value, 2, $Fmt));
     2988            }
     2989            else
     2990            {
     2991                $Value = specChars($Value);
     2992                if($Attr ne "Type_Type") {
     2993                    $Value = "<b>".$Value."</b>";
     2994                }
     2995            }
     2996        }
     2997        $Content=~s/\Q$Macro\E/$Value/g;
     2998    }
     2999   
     3000    if($Content=~/(\A|[^\@\w])(\@\w+)/)
     3001    {
     3002        if(not $IncompleteRules{$Level}{$Kind})
     3003        { # only one warning
     3004            printMsg("WARNING", "incomplete $2 in the rule \"$Kind\" (\"$Level\")");
     3005            $IncompleteRules{$Level}{$Kind} = 1;
     3006        }
     3007    }
     3008   
     3009    return $Content;
     3010}
     3011
     3012sub getReportMethodProblems($$)
    40223013{
    40233014    my ($TargetSeverity, $Level) = @_;
     
    40283019    {
    40293020        my $ArchiveName = $MethodInfo{1}{$Method}{"Archive"};
    4030         my $ClassName = get_ShortName($MethodInfo{1}{$Method}{"Class"}, 1);
     3021        my $ClassName = getShortName($MethodInfo{1}{$Method}{"Class"}, 1);
    40313022       
    40323023        foreach my $Kind (sort keys(%{$CompatProblems{$Method}}))
    40333024        {
    4034             if($Kind eq "Added_Method"
    4035             or $Kind eq "Removed_Method") {
    4036                 next;
    4037             }
    4038            
    4039             if(my $Severity = $MethodProblems_Kind{$Level}{$Kind})
    4040             {
    4041                 if($Severity ne $TargetSeverity) {
     3025            if($CompatRules{$Level}{$Kind}{"Kind"} eq "Methods")
     3026            {
     3027                if($Kind eq "Added_Method"
     3028                or $Kind eq "Removed_Method") {
    40423029                    next;
    40433030                }
    40443031               
    4045                 $MethodChanges{$Method}{$Kind} = $CompatProblems{$Method}{$Kind};
    4046                 $ReportMap{$ArchiveName}{$ClassName}{$Method} = 1;
     3032                if(my $Severity = $CompatRules{$Level}{$Kind}{"Severity"})
     3033                {
     3034                    if($Severity ne $TargetSeverity) {
     3035                        next;
     3036                    }
     3037                   
     3038                    $MethodChanges{$Method}{$Kind} = $CompatProblems{$Method}{$Kind};
     3039                    $ReportMap{$ArchiveName}{$ClassName}{$Method} = 1;
     3040                }
    40473041            }
    40483042        }
     
    40633057            foreach my $NameSpace (sort keys(%NameSpace_Method))
    40643058            {
    4065                 $METHOD_PROBLEMS .= "<span class='jar'>$ArchiveName</span>, <span class='cname'>".htmlSpecChars($ShowClass).".class</span><br/>\n";
     3059                $METHOD_PROBLEMS .= "<span class='jar'>$ArchiveName</span>, <span class='cname'>".specChars($ShowClass).".class</span><br/>\n";
    40663060                if($NameSpace) {
    40673061                    $METHOD_PROBLEMS .= "<span class='pkg_t'>package</span> <span class='pkg'>$NameSpace</span><br/>\n";
     
    40713065                foreach my $Method (@SortedMethods)
    40723066                {
    4073                     my $ShortSignature = get_Signature($Method, 1, "Short");
    4074                     my $ClassName_Full = get_TypeName($MethodInfo{1}{$Method}{"Class"}, 1);
     3067                    my %AddAttr = ();
     3068                   
     3069                    $AddAttr{"Method_Short"} = $Method;
     3070                    $AddAttr{"Class"} = getTypeName($MethodInfo{1}{$Method}{"Class"}, 1);
     3071                   
    40753072                    my $METHOD_REPORT = "";
    40763073                    my $ProblemNum = 1;
    40773074                    foreach my $Kind (sort keys(%{$MethodChanges{$Method}}))
    40783075                    {
    4079                         foreach my $Location (sort keys(%{$MethodChanges{$Method}{$Kind}}))
     3076                        foreach my $Loc (sort keys(%{$MethodChanges{$Method}{$Kind}}))
    40803077                        {
    4081                             my %Problems = %{$MethodChanges{$Method}{$Kind}{$Location}};
     3078                            my $ProblemAttr = $MethodChanges{$Method}{$Kind}{$Loc};
    40823079                           
    4083                             my $Target = $Problems{"Target"};
    4084                            
    4085                             my ($Change, $Effect) = ("", "");
    4086                             my $Old_Value = htmlSpecChars($Problems{"Old_Value"});
    4087                             my $New_Value = htmlSpecChars($Problems{"New_Value"});
    4088                            
    4089                             if($Kind eq "Method_Became_Static")
     3080                            if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $ProblemAttr, \%AddAttr))
    40903081                            {
    4091                                 $Change = "Method became <b>static</b>.\n";
    4092                                 $Effect = "A client program may be interrupted by <b>NoSuchMethodError</b> exception.";
    4093                             }
    4094                             elsif($Kind eq "Method_Became_NonStatic")
    4095                             {
    4096                                 $Change = "Method became <b>non-static</b>.\n";
    4097                                 if($Level eq "Binary") {
    4098                                     $Effect = "A client program may be interrupted by <b>NoSuchMethodError</b> exception.";
    4099                                 }
    4100                                 else {
    4101                                     $Effect = "Recompilation of a client program may be terminated with the message: non-static method ".htmlSpecChars($ShortSignature)." cannot be referenced from a static context.";
    4102                                 }
    4103                             }
    4104                             elsif($Kind eq "Changed_Method_Return_From_Void")
    4105                             {
    4106                                 $Change = "Return value type has been changed from <b>void</b> to <b>".htmlSpecChars($New_Value)."</b>.\n";
    4107                                 $Effect = "This method has been removed because the return type is part of the method signature.";
    4108                             }
    4109                             elsif($Kind eq "Static_Method_Became_Final")
    4110                             {# Source Only
    4111                                 $Change = "Method became <b>final</b>.\n";
    4112                                 $Effect = "Recompilation of a client program may be terminated with the message: ".htmlSpecChars($ShortSignature)." in client class C cannot override ".htmlSpecChars($ShortSignature)." in ".htmlSpecChars($ClassName_Full)."; overridden method is final.";
    4113                             }
    4114                             elsif($Kind eq "NonStatic_Method_Became_Final")
    4115                             {
    4116                                 $Change = "Method became <b>final</b>.\n";
    4117                                 if($Level eq "Binary") {
    4118                                     $Effect = "A client program trying to reimplement this method may be interrupted by <b>VerifyError</b> exception.";
    4119                                 }
    4120                                 else {
    4121                                     $Effect = "Recompilation of a client program may be terminated with the message: ".htmlSpecChars($ShortSignature)." in client class C cannot override ".htmlSpecChars($ShortSignature)." in ".htmlSpecChars($ClassName_Full)."; overridden method is final.";
    4122                                 }
    4123                             }
    4124                             elsif($Kind eq "Method_Became_Abstract")
    4125                             {
    4126                                 $Change = "Method became <b>abstract</b>.\n";
    4127                                 if($Level eq "Binary") {
    4128                                     $Effect = "A client program trying to create an instance of the method's class may be interrupted by <b>InstantiationError</b> exception.";
    4129                                 }
    4130                                 else {
    4131                                     $Effect = "Recompilation of a client program may be terminated with the message: A client class C is not abstract and does not override abstract method ".htmlSpecChars($ShortSignature)." in ".htmlSpecChars($ClassName_Full).".";
    4132                                 }
    4133                             }
    4134                             elsif($Kind eq "Method_Became_NonAbstract")
    4135                             {
    4136                                 $Change = "Method became <b>non-abstract</b>.\n";
    4137                                 if($Level eq "Binary") {
    4138                                     $Effect = "A client program may change behavior.";
    4139                                 }
    4140                                 else {
    4141                                     $Effect = "No effect.";
    4142                                 }
    4143                             }
    4144                             elsif($Kind eq "Method_Became_Default")
    4145                             {
    4146                                 $Change = "Method became <b>default</b>.\n";
    4147                                 if($Level eq "Binary") {
    4148                                     $Effect = "No effect.";
    4149                                 }
    4150                                 else {
    4151                                     $Effect = "No effect.";
    4152                                 }
    4153                             }
    4154                             elsif($Kind eq "Method_Became_NonDefault")
    4155                             {
    4156                                 $Change = "Method became <b>non-default</b>.\n";
    4157                                 if($Level eq "Binary") {
    4158                                     $Effect = "A client program trying to create an instance of a class may be interrupted by <b>AbstractMethodError</b> exception.";
    4159                                 }
    4160                                 else {
    4161                                     $Effect = "Recompilation of a client program may be terminated with the message: A client class C is not abstract and does not override abstract method ".htmlSpecChars($ShortSignature)." in ".htmlSpecChars($ClassName_Full).".";
    4162                                 }
    4163                             }
    4164                             elsif($Kind eq "Method_Became_Synchronized")
    4165                             {
    4166                                 $Change = "Method became <b>synchronized</b>.\n";
    4167                                 $Effect = "A multi-threaded client program may change behavior.";
    4168                             }
    4169                             elsif($Kind eq "Method_Became_NonSynchronized")
    4170                             {
    4171                                 $Change = "Method became <b>non-synchronized</b>.\n";
    4172                                 $Effect = "A multi-threaded client program may change behavior.";
    4173                             }
    4174                             elsif($Kind eq "Changed_Method_Access")
    4175                             {
    4176                                 $Change = "Access level has been changed from <span class='nowrap'><b>".htmlSpecChars($Old_Value)."</b></span> to <span class='nowrap'><b>".htmlSpecChars($New_Value)."</b></span>.";
    4177                                 if($Level eq "Binary") {
    4178                                     $Effect = "A client program may be interrupted by <b>IllegalAccessError</b> exception.";
    4179                                 }
    4180                                 else {
    4181                                     $Effect = "Recompilation of a client program may be terminated with the message: ".htmlSpecChars($ShortSignature)." has $New_Value access in ".htmlSpecChars($ClassName_Full).".";
    4182                                 }
    4183                             }
    4184                             elsif($Kind eq "Abstract_Method_Added_Checked_Exception")
    4185                             {# Source Only
    4186                                 $Change = "Added <b>".htmlSpecChars($Target)."</b> exception thrown.\n";
    4187                                 $Effect = "Recompilation of a client program may be terminated with the message: unreported exception ".htmlSpecChars($Target)." must be caught or declared to be thrown.";
    4188                             }
    4189                             elsif($Kind eq "NonAbstract_Method_Added_Checked_Exception")
    4190                             {
    4191                                 $Change = "Added <b>".htmlSpecChars($Target)."</b> exception thrown.\n";
    4192                                 if($Level eq "Binary") {
    4193                                     $Effect = "A client program may be interrupted by added exception.";
    4194                                 }
    4195                                 else {
    4196                                     $Effect = "Recompilation of a client program may be terminated with the message: unreported exception ".htmlSpecChars($Target)." must be caught or declared to be thrown.";
    4197                                 }
    4198                             }
    4199                             elsif($Kind eq "Abstract_Method_Removed_Checked_Exception")
    4200                             {# Source Only
    4201                                 $Change = "Removed <b>".htmlSpecChars($Target)."</b> exception thrown.\n";
    4202                                 $Effect = "Recompilation of a client program may be terminated with the message: cannot override ".htmlSpecChars($ShortSignature)." in ".htmlSpecChars($ClassName_Full)."; overridden method does not throw ".htmlSpecChars($Target).".";
    4203                             }
    4204                             elsif($Kind eq "NonAbstract_Method_Removed_Checked_Exception")
    4205                             {
    4206                                 $Change = "Removed <b>".htmlSpecChars($Target)."</b> exception thrown.\n";
    4207                                 if($Level eq "Binary") {
    4208                                     $Effect = "A client program may change behavior because the removed exception will not be thrown any more and client will not catch and handle it.";
    4209                                 }
    4210                                 else {
    4211                                     $Effect = "Recompilation of a client program may be terminated with the message: cannot override ".htmlSpecChars($ShortSignature)." in ".htmlSpecChars($ClassName_Full)."; overridden method does not throw ".htmlSpecChars($Target).".";
    4212                                 }
    4213                             }
    4214                             elsif($Kind eq "Added_Unchecked_Exception")
    4215                             {# Binary Only
    4216                                 $Change = "Added <b>".htmlSpecChars($Target)."</b> exception thrown.\n";
    4217                                 $Effect = "A client program may be interrupted by added exception.";
    4218                             }
    4219                             elsif($Kind eq "Removed_Unchecked_Exception")
    4220                             {# Binary Only
    4221                                 $Change = "Removed <b>".htmlSpecChars($Target)."</b> exception thrown.\n";
    4222                                 $Effect = "A client program may change behavior because the removed exception will not be thrown any more and client will not catch and handle it.";
    4223                             }
    4224                             if($Change)
    4225                             {
    4226                                 $METHOD_REPORT .= "<tr><th>$ProblemNum</th><td>".$Change."</td><td>".$Effect."</td></tr>\n";
     3082                                my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, $ProblemAttr, \%AddAttr);
     3083                                $METHOD_REPORT .= "<tr>\n<th>$ProblemNum</th>\n<td>".$Change."</td>\n<td>".$Effect."</td>\n</tr>\n";
    42273084                                $ProblemNum += 1;
    42283085                                $ProblemsNum += 1;
     
    42333090                    if($METHOD_REPORT)
    42343091                    {
    4235                         my $ShowMethod = highLight_Signature_Italic_Color($Method, 1);
     3092                        my $ShowMethod = highLight_ItalicColor($Method, 1);
    42363093                        if($NameSpace)
    42373094                        {
    4238                             $METHOD_REPORT = cut_Namespace($METHOD_REPORT, $NameSpace);
    4239                             $ShowMethod = cut_Namespace($ShowMethod, $NameSpace);
     3095                            $METHOD_REPORT = cutNs($METHOD_REPORT, $NameSpace);
     3096                            $ShowMethod = cutNs($ShowMethod, $NameSpace);
    42403097                        }
    42413098                       
    42423099                        $METHOD_PROBLEMS .= $ContentSpanStart."<span class='ext'>[+]</span> ".$ShowMethod;
    4243                         if($OldStyle) {
     3100                        if($In::Opt{"OldStyle"}) {
    42443101                            $METHOD_PROBLEMS .= " ($ProblemNum)";
    42453102                        }
     
    42503107                        $METHOD_PROBLEMS .= $ContentDivStart;
    42513108                       
    4252                         if(not $Compact) {
    4253                             $METHOD_PROBLEMS .= "<span class='mngl'>&#160;&#160;&#160;[mangled: <b>".htmlSpecChars($Method)."</b>]</span><br/>\n";
     3109                        if(not $In::Opt{"Compact"}) {
     3110                            $METHOD_PROBLEMS .= "<span class='mngl pleft'>".specChars($Method)."</span><br/>\n";
    42543111                        }
    42553112                       
     
    42723129            $Title = "Other Changes in Methods";
    42733130        }
    4274         if($OldStyle) {
     3131        if($In::Opt{"OldStyle"}) {
    42753132            $METHOD_PROBLEMS = "<h2>$Title ($ProblemsNum)</h2><hr/>\n".$METHOD_PROBLEMS;
    42763133        }
     
    42783135            $METHOD_PROBLEMS = "<h2>$Title <span".getStyle("M", $TargetSeverity, $ProblemsNum).">&nbsp;$ProblemsNum&nbsp;</span></h2><hr/>\n".$METHOD_PROBLEMS;
    42793136        }
    4280         $METHOD_PROBLEMS = "<a name='".get_Anchor("Method", $Level, $TargetSeverity)."'></a>\n".$METHOD_PROBLEMS;
     3137        $METHOD_PROBLEMS = "<a name='".getAnchor("Method", $Level, $TargetSeverity)."'></a>\n".$METHOD_PROBLEMS;
    42813138        $METHOD_PROBLEMS .= $TOP_REF."<br/>\n";
    42823139    }
     
    42843141}
    42853142
    4286 sub get_Report_TypeProblems($$)
     3143sub showType($$$)
     3144{
     3145    my ($Name, $Html, $LVer) = @_;
     3146    my $TType = $TypeInfo{$LVer}{$TName_Tid{$LVer}{$Name}}{"Type"};
     3147    if($Html) {
     3148        $Name = "<span class='ttype'>".$TType."</span> ".specChars($Name);
     3149    }
     3150    else {
     3151        $Name = $TType." ".$Name;
     3152    }
     3153    return $Name;
     3154}
     3155
     3156sub getReportTypeProblems($$)
    42873157{
    42883158    my ($TargetSeverity, $Level) = @_;
    42893159    my $TYPE_PROBLEMS = "";
     3160   
    42903161    my %ReportMap = ();
    42913162    my %TypeChanges_Sev = ();
     
    42973168        foreach my $Kind (keys(%{$TypeChanges{$Level}{$TypeName}}))
    42983169        {
    4299             my $Severity = $TypeProblems_Kind{$Level}{$Kind};
     3170            if($CompatRules{$Level}{$Kind}{"Severity"} ne $TargetSeverity) {
     3171                next;
     3172            }
    43003173           
    4301             if($Severity ne $TargetSeverity) {
    4302                 next;
    4303             }
    4304            
    4305             foreach my $Location (keys(%{$TypeChanges{$Level}{$TypeName}{$Kind}}))
     3174            foreach my $Loc (keys(%{$TypeChanges{$Level}{$TypeName}{$Kind}}))
    43063175            {
    43073176                $ReportMap{$ArchiveName}{$TypeName} = 1;
    4308                 $TypeChanges_Sev{$TypeName}{$Kind}{$Location} = $TypeChanges{$Level}{$TypeName}{$Kind}{$Location};
     3177                $TypeChanges_Sev{$TypeName}{$Kind}{$Loc} = $TypeChanges{$Level}{$TypeName}{$Kind}{$Loc};
    43093178            }
    43103179        }
     
    43143183    foreach my $ArchiveName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
    43153184    {
    4316         my ($HEADER_REPORT, %NameSpace_Type) = ();
    4317         foreach my $TypeName (keys(%{$ReportMap{$ArchiveName}}))
    4318         {
     3185        my %NameSpace_Type = ();
     3186        foreach my $TypeName (keys(%{$ReportMap{$ArchiveName}})) {
    43193187            $NameSpace_Type{$TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Package"}}{$TypeName} = 1;
    43203188        }
     
    43263194            }
    43273195           
    4328             my @SortedTypes = sort {lc($a) cmp lc($b)} keys(%{$NameSpace_Type{$NameSpace}});
     3196            my @SortedTypes = sort {lc(showType($a, 0, 1)) cmp lc(showType($b, 0, 1))} keys(%{$NameSpace_Type{$NameSpace}});
    43293197            foreach my $TypeName (@SortedTypes)
    43303198            {
    43313199                my $TypeId = $TName_Tid{1}{$TypeName};
     3200               
    43323201                my $ProblemNum = 1;
    43333202                my $TYPE_REPORT = "";
    43343203                my (%Kinds_Locations, %Kinds_Target) = ();
     3204               
    43353205                foreach my $Kind (sort keys(%{$TypeChanges_Sev{$TypeName}}))
    43363206                {
     
    43453215                        $Kinds_Target{$Kind}{$Target} = 1;
    43463216                       
    4347                         my ($Change, $Effect) = ("", "");
    4348                         my %Problems = %{$TypeChanges_Sev{$TypeName}{$Kind}{$Location}};
     3217                        my %AddAttr = ();
    43493218                       
    4350                         my $Old_Value = $Problems{"Old_Value"};
    4351                         my $New_Value = $Problems{"New_Value"};
    4352                         my $Field_Type = $Problems{"Field_Type"};
    4353                         my $Field_Value = $Problems{"Field_Value"};
    4354                         my $Type_Type = $Problems{"Type_Type"};
    4355                        
    4356                         if($Kind eq "NonAbstract_Class_Added_Abstract_Method")
     3219                        if($Kind=~/Method/)
    43573220                        {
    4358                             $Change = "Abstract method ".black_Name($Target, 2)." has been added to this $Type_Type.";
    4359                             if($Level eq "Binary") {
    4360                                 $Effect = "This class became <b>abstract</b> and a client program may be interrupted by <b>InstantiationError</b> exception.";
     3221                            if(defined $MethodInfo{1}{$Target} and $MethodInfo{1}{$Target}{"Name"})
     3222                            {
     3223                                $AddAttr{"Method_Short"} = $Target;
     3224                                $AddAttr{"Class"} = getTypeName($MethodInfo{1}{$Target}{"Class"}, 1);
    43613225                            }
    4362                             else {
    4363                                 $Effect = "Recompilation of a client program may be terminated with the message: a client class C is not abstract and does not override abstract method <b>".htmlSpecChars(get_Signature($Target, 2, "Short"))."</b> in <b>".htmlSpecChars(get_TypeName($MethodInfo{2}{$Target}{"Class"}, 2))."</b>.";
     3226                            elsif(defined $MethodInfo{2}{$Target} and $MethodInfo{2}{$Target}{"Name"})
     3227                            {
     3228                                $AddAttr{"Method_Short"} = $Target;
     3229                                $AddAttr{"Class"} = getTypeName($MethodInfo{2}{$Target}{"Class"}, 2);
    43643230                            }
    43653231                        }
    4366                         elsif($Kind eq "Abstract_Class_Added_Abstract_Method")
     3232                       
     3233                        my $ProblemAttr = $TypeChanges_Sev{$TypeName}{$Kind}{$Location};
     3234                       
     3235                        if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $ProblemAttr, \%AddAttr))
    43673236                        {
    4368                             $Change = "Abstract method ".black_Name($Target, 2)." has been added to this $Type_Type.";
    4369                             if($Level eq "Binary") {
    4370                                 $Effect = "No effect.";
    4371                             }
    4372                             else {
    4373                                 $Effect = "Recompilation of a client program may be terminated with the message: a client class C is not abstract and does not override abstract method <b>".htmlSpecChars(get_Signature($Target, 2, "Short"))."</b> in <b>".htmlSpecChars(get_TypeName($MethodInfo{2}{$Target}{"Class"}, 2))."</b>.";
    4374                             }
    4375                         }
    4376                         elsif($Kind eq "Abstract_Class_Added_Abstract_Method_Invoked_By_Others")
    4377                         {
    4378                             $Change = "Abstract method ".black_Name($Target, 2)." has been added to this $Type_Type.";
    4379                             if($Level eq "Binary") {
    4380                                 $Effect = "A client program may be interrupted by <b>AbstractMethodError</b> exception. Added abstract method is called in 2nd library version by the method ".black_Name($Problems{"InvokedBy"}, 1)." and may not be implemented by old clients.";
    4381                             }
    4382                             else {
    4383                                 $Effect = "Recompilation of a client program may be terminated with the message: a client class C is not abstract and does not override abstract method <b>".htmlSpecChars(get_Signature($Target, 2, "Short"))."</b> in <b>".htmlSpecChars(get_TypeName($MethodInfo{2}{$Target}{"Class"}, 2))."</b>.";
    4384                             }
    4385                         }
    4386                         elsif($Kind eq "Class_Removed_Abstract_Method"
    4387                         or $Kind eq "Interface_Removed_Abstract_Method")
    4388                         {
    4389                             $Change = "Abstract method ".black_Name($Target, 1)." has been removed from this $Type_Type.";
    4390                             if($Level eq "Binary") {
    4391                                 $Effect = "A client program may be interrupted by <b>NoSuchMethodError</b> exception.";
    4392                             }
    4393                             else {
    4394                                 $Effect = "Recompilation of a client program may be terminated with the message: cannot find method <b>".htmlSpecChars(get_Signature($Target, 1, "Short"))."</b> in $Type_Type <b>".htmlSpecChars(get_TypeName($MethodInfo{1}{$Target}{"Class"}, 1))."</b>.";
    4395                             }
    4396                         }
    4397                         elsif($Kind eq "Interface_Added_Abstract_Method")
    4398                         {
    4399                             $Change = "Abstract method ".black_Name($Target, 2)." has been added to this $Type_Type.";
    4400                             if($Level eq "Binary") {
    4401                                 $Effect = "No effect.";
    4402                             }
    4403                             else {
    4404                                 $Effect = "Recompilation of a client program may be terminated with the message: a client class C is not abstract and does not override abstract method <b>".htmlSpecChars(get_Signature($Target, 2, "Short"))."</b> in <b>".htmlSpecChars(get_TypeName($MethodInfo{2}{$Target}{"Class"}, 2))."</b>.";
    4405                             }
    4406                         }
    4407                         elsif($Kind eq "Interface_Added_Abstract_Method_Invoked_By_Others")
    4408                         {
    4409                             $Change = "Abstract method ".black_Name($Target, 2)." has been added to this $Type_Type.";
    4410                             if($Level eq "Binary") {
    4411                                 $Effect = "A client program may be interrupted by <b>AbstractMethodError</b> exception. Added abstract method is called in 2nd library version by the method ".black_Name($Problems{"InvokedBy"}, 1)." and may not be implemented by old clients.";
    4412                             }
    4413                             else {
    4414                                 $Effect = "Recompilation of a client program may be terminated with the message: a client class C is not abstract and does not override abstract method <b>".htmlSpecChars(get_Signature($Target, 2, "Short"))."</b> in <b>".htmlSpecChars(get_TypeName($MethodInfo{2}{$Target}{"Class"}, 2))."</b>.";
    4415                             }
    4416                         }
    4417                         elsif($Kind eq "Class_Method_Became_Abstract")
    4418                         {
    4419                             $Change = "Method ".black_Name($Target, 1)." became <b>abstract</b>.";
    4420                             if($Level eq "Binary") {
    4421                                 $Effect = "A client program may be interrupted by <b>InstantiationError</b> exception.";
    4422                             }
    4423                             else {
    4424                                 $Effect = "Recompilation of a client program may be terminated with the message: a client class C is not abstract and does not override abstract method <b>".htmlSpecChars(get_Signature($Target, 1, "Short"))."</b> in <b>".htmlSpecChars(get_TypeName($MethodInfo{1}{$Target}{"Class"}, 1))."</b>.";
    4425                             }
    4426                         }
    4427                         elsif($Kind eq "Class_Method_Became_NonAbstract")
    4428                         {
    4429                             $Change = "Abstract method ".black_Name($Target, 1)." became <b>non-abstract</b>.";
    4430                             if($Level eq "Binary") {
    4431                                 $Effect = "Some methods in this class may change behavior.";
    4432                             }
    4433                             else {
    4434                                 $Effect = "No effect.";
    4435                             }
    4436                         }
    4437                         elsif($Kind eq "Interface_Method_Became_NonDefault")
    4438                         {
    4439                             $Change = "Method ".black_Name($Target, 1)." became <b>non-default</b>.";
    4440                             if($Level eq "Binary") {
    4441                                 $Effect = "A client program may be interrupted by <b>AbstractMethodError</b> exception.";
    4442                             }
    4443                             else {
    4444                                 $Effect = "Recompilation of a client program may be terminated with the message: a client class C is not abstract and does not override abstract method <b>".htmlSpecChars(get_Signature($Target, 1, "Short"))."</b> in <b>".htmlSpecChars(get_TypeName($MethodInfo{1}{$Target}{"Class"}, 1))."</b>.";
    4445                             }
    4446                         }
    4447                         elsif($Kind eq "Interface_Method_Became_Default")
    4448                         {
    4449                             $Change = "Method ".black_Name($Target, 1)." became <b>default</b>.";
    4450                             if($Level eq "Binary") {
    4451                                 $Effect = "No effect.";
    4452                             }
    4453                             else {
    4454                                 $Effect = "No effect.";
    4455                             }
    4456                         }
    4457                         elsif($Kind eq "Class_Overridden_Method")
    4458                         {
    4459                             $Change = "Method ".black_Name($Old_Value, 2)." has been overridden by ".black_Name($New_Value, 2);
    4460                             $Effect = "Method ".black_Name($New_Value, 2)." will be called instead of ".black_Name($Old_Value, 2)." in a client program.";
    4461                         }
    4462                         elsif($Kind eq "Class_Method_Moved_Up_Hierarchy")
    4463                         {
    4464                             $Change = "Method ".black_Name($Old_Value, 1)." has been moved up type hierarchy to ".black_Name($New_Value, 2);
    4465                             $Effect = "Method ".black_Name($New_Value, 2)." will be called instead of ".black_Name($Old_Value, 1)." in a client program.";
    4466                         }
    4467                         elsif($Kind eq "Abstract_Class_Added_Super_Interface")
    4468                         {
    4469                             $Change = "Added super-interface <b>".htmlSpecChars($Target)."</b>.";
    4470                             if($Level eq "Binary")
    4471                             {
    4472                                 $Effect = "No effect.";
    4473                             }
    4474                             else {
    4475                                 $Effect = "Recompilation of a client program may be terminated with the message: a client class C is not abstract and does not override abstract method in <b>".htmlSpecChars($Target)."</b>.";
    4476                             }
    4477                         }
    4478                         elsif($Kind eq "Abstract_Class_Added_Super_Interface_Invoked_By_Others")
    4479                         {
    4480                             $Change = "Added super-interface <b>".htmlSpecChars($Target)."</b>.";
    4481                             if($Level eq "Binary") {
    4482                                 $Effect = "If abstract methods from an added super-interface must be implemented by client then it may be interrupted by <b>AbstractMethodError</b> exception.<br/><br/>Abstract method ".black_Name_S(htmlSpecChars($Problems{"Invoked"}))." from the added super-interface is called by the method ".black_Name($Problems{"InvokedBy"}, 2)." in 2nd library version and may not be implemented by old clients.";
    4483                             }
    4484                             else {
    4485                                 $Effect = "Recompilation of a client program may be terminated with the message: a client class C is not abstract and does not override abstract method in <b>".htmlSpecChars($Target)."</b>.";
    4486                             }
    4487                         }
    4488                         elsif($Kind eq "Abstract_Class_Added_Super_Interface_With_Implemented_Methods")
    4489                         {
    4490                             $Change = "Added super-interface <b>".htmlSpecChars($Target)."</b>.";
    4491                             $Effect = "No effect.";
    4492                         }
    4493                         elsif($Kind eq "Interface_Added_Super_Interface")
    4494                         {
    4495                             $Change = "Added super-interface <b>".htmlSpecChars($Target)."</b>.";
    4496                             if($Level eq "Binary") {
    4497                                 $Effect = "No effect.";
    4498                             }
    4499                             else {
    4500                                 $Effect = "Recompilation of a client program may be terminated with the message: a client class C is not abstract and does not override abstract method in <b>".htmlSpecChars($Target)."</b>.";
    4501                             }
    4502                         }
    4503                         elsif($Kind eq "Interface_Added_Super_Interface_Used_By_Others")
    4504                         {
    4505                             $Change = "Added super-interface <b>".htmlSpecChars($Target)."</b>.";
    4506                             if($Level eq "Binary")
    4507                             {
    4508                                 $Effect = "If abstract methods from an added super-interface must be implemented by client then it may be interrupted by <b>AbstractMethodError</b> exception.<br/><br/>Abstract method ".black_Name_S(htmlSpecChars($Problems{"Invoked"}))." from the added super-interface is called by the method ".black_Name($Problems{"InvokedBy"}, 2)." in 2nd library version and may not be implemented by old clients.";
    4509                             }
    4510                             else {
    4511                                 $Effect = "Recompilation of a client program may be terminated with the message: a client class C is not abstract and does not override abstract method in <b>".htmlSpecChars($Target)."</b>.";
    4512                             }
    4513                         }
    4514                         elsif($Kind eq "Interface_Added_Super_Interface_With_Implemented_Methods")
    4515                         {
    4516                             $Change = "Added super-interface <b>".htmlSpecChars($Target)."</b>.";
    4517                             if($Level eq "Binary") {
    4518                                 $Effect = "No effect.";
    4519                             }
    4520                             else {
    4521                                 $Effect = "No effect.";
    4522                             }
    4523                         }
    4524                         elsif($Kind eq "Interface_Added_Super_Constant_Interface")
    4525                         {
    4526                             $Change = "Added super-interface <b>".htmlSpecChars($Target)."</b> containing constants only.";
    4527                             if($Level eq "Binary") {
    4528                                 $Effect = "A static field from a super-interface of a client class may hide a field (with the same name) inherited from a super-class and cause <b>IncompatibleClassChangeError</b> exception.";
    4529                             }
    4530                             else {
    4531                                 $Effect = "A static field from a super-interface of a client class may hide a field (with the same name) inherited from a super-class. Recompilation of a client class may be terminated with the message: reference to variable is ambiguous.";
    4532                             }
    4533                         }
    4534                         elsif($Kind eq "Interface_Removed_Super_Interface"
    4535                         or $Kind eq "Class_Removed_Super_Interface")
    4536                         {
    4537                             $Change = "Removed super-interface <b>".htmlSpecChars($Target)."</b>.";
    4538                             if($Level eq "Binary") {
    4539                                 $Effect = "A client program may be interrupted by <b>NoSuchMethodError</b> exception.";
    4540                             }
    4541                             else {
    4542                                 $Effect = "Recompilation of a client program may be terminated with the message: cannot find method in $Type_Type <b>".htmlSpecChars($TypeName)."</b>.";
    4543                             }
    4544                         }
    4545                         elsif($Kind eq "Interface_Removed_Super_Constant_Interface")
    4546                         {
    4547                             $Change = "Removed super-interface <b>".htmlSpecChars($Target)."</b> containing constants only.";
    4548                             if($Level eq "Binary") {
    4549                                 $Effect = "No effect.";
    4550                             }
    4551                             else {
    4552                                 $Effect = "Recompilation of a client program may be terminated with the message: cannot find variable in $Type_Type <b>".htmlSpecChars($TypeName)."</b>.";
    4553                             }
    4554                         }
    4555                         elsif($Kind eq "Added_Super_Class")
    4556                         {
    4557                             $Change = "Added super-class <b>".htmlSpecChars($Target)."</b>.";
    4558                             if($Level eq "Binary") {
    4559                                 $Effect = "A static field from a super-interface of a client class may hide a field (with the same name) inherited from new super-class and cause <b>IncompatibleClassChangeError</b> exception.";
    4560                             }
    4561                             else {
    4562                                 $Effect = "A static field from a super-interface of a client class may hide a field (with the same name) inherited from new super-class. Recompilation of a client class may be terminated with the message: reference to variable is ambiguous.";
    4563                             }
    4564                         }
    4565                         elsif($Kind eq "Abstract_Class_Added_Super_Abstract_Class")
    4566                         {
    4567                             $Change = "Added abstract super-class <b>".htmlSpecChars($Target)."</b>.";
    4568                             if($Level eq "Binary") {
    4569                                 $Effect = "No effect.";
    4570                             }
    4571                             else {
    4572                                 $Effect = "Recompilation of a client program may be terminated with the message: a client class C is not abstract and does not override abstract method in <b>".htmlSpecChars($Target)."</b>.";
    4573                             }
    4574                         }
    4575                         elsif($Kind eq "Abstract_Class_Added_Super_Abstract_Class_Invoked_By_Others")
    4576                         {
    4577                             $Change = "Added abstract super-class <b>".htmlSpecChars($Target)."</b>.";
    4578                             if($Level eq "Binary") {
    4579                                 $Effect = "If abstract methods from an added super-class must be implemented by client then it may be interrupted by <b>AbstractMethodError</b> exception.<br/><br/>Abstract method ".black_Name_S(htmlSpecChars($Problems{"Invoked"}))." from the added abstract super-class is called by the method ".black_Name($Problems{"InvokedBy"}, 2)." in 2nd library version and may not be implemented by old clients.";
    4580                             }
    4581                             else {
    4582                                 $Effect = "Recompilation of a client program may be terminated with the message: a client class C is not abstract and does not override abstract method in <b>".htmlSpecChars($Target)."</b>.";
    4583                             }
    4584                         }
    4585                         elsif($Kind eq "Removed_Super_Class")
    4586                         {
    4587                             $Change = "Removed super-class <b>".htmlSpecChars($Target)."</b>.";
    4588                             if($Level eq "Binary") {
    4589                                 $Effect = "Access of a client program to the fields or methods of the old super-class may be interrupted by <b>NoSuchFieldError</b> or <b>NoSuchMethodError</b> exceptions.";
    4590                             }
    4591                             else {
    4592                                 $Effect = "Recompilation of a client program may be terminated with the message: cannot find variable (or method) in <b>".htmlSpecChars($TypeName)."</b>.";
    4593                             }
    4594                         }
    4595                         elsif($Kind eq "Changed_Super_Class")
    4596                         {
    4597                             $Change = "Superclass has been changed from <b>".htmlSpecChars($Old_Value)."</b> to <b>".htmlSpecChars($New_Value)."</b>.";
    4598                             if($Level eq "Binary") {
    4599                                 $Effect = "1) Access of a client program to the fields or methods of the old super-class may be interrupted by <b>NoSuchFieldError</b> or <b>NoSuchMethodError</b> exceptions.<br/>2) A static field from a super-interface of a client class may hide a field (with the same name) inherited from new super-class and cause <b>IncompatibleClassChangeError</b> exception.";
    4600                             }
    4601                             else {
    4602                                 $Effect = "1) Recompilation of a client program may be terminated with the message: cannot find variable (or method) in <b>".htmlSpecChars($TypeName)."</b>.<br/>2) A static field from a super-interface of a client class may hide a field (with the same name) inherited from new super-class. Recompilation of a client class may be terminated with the message: reference to variable is ambiguous.";
    4603                             }
    4604                         }
    4605                         elsif($Kind eq "Class_Added_Field")
    4606                         {
    4607                             $Change = "Field <b>$Target</b> has been added to this class.";
    4608                             if($Level eq "Binary")
    4609                             {
    4610                                 $Effect = "No effect.";
    4611                                 # $Effect .= "<br/><b>NOTE</b>: A static field from a super-interface of a client class may hide an added field (with the same name) inherited from the super-class of a client class and cause <b>IncompatibleClassChangeError</b> exception.";
    4612                             }
    4613                             else
    4614                             {
    4615                                 $Effect = "No effect.";
    4616                                 # $Effect .= "<br/><b>NOTE</b>: A static field from a super-interface of a client class may hide an added field (with the same name) inherited from the super-class of a client class. Recompilation of a client class may be terminated with the message: reference to <b>$Target</b> is ambiguous.";
    4617                             }
    4618                         }
    4619                         elsif($Kind eq "Interface_Added_Field")
    4620                         {
    4621                             $Change = "Field <b>$Target</b> has been added to this interface.";
    4622                             if($Level eq "Binary") {
    4623                                 $Effect = "No effect.<br/><b>NOTE</b>: An added static field from a super-interface of a client class may hide a field (with the same name) inherited from the super-class of a client class and cause <b>IncompatibleClassChangeError</b> exception.";
    4624                             }
    4625                             else {
    4626                                 $Effect = "No effect.<br/><b>NOTE</b>: An added static field from a super-interface of a client class may hide a field (with the same name) inherited from the super-class of a client class. Recompilation of a client class may be terminated with the message: reference to <b>$Target</b> is ambiguous.";
    4627                             }
    4628                         }
    4629                         elsif($Kind eq "Renamed_Field")
    4630                         {
    4631                             $Change = "Field <b>$Target</b> has been renamed to <b>".htmlSpecChars($New_Value)."</b>.";
    4632                             if($Level eq "Binary") {
    4633                                 $Effect = "A client program may be interrupted by <b>NoSuchFieldError</b> exception.";
    4634                             }
    4635                             else {
    4636                                 $Effect = "Recompilation of a client program may be terminated with the message: cannot find variable <b>$Target</b> in <b>".htmlSpecChars($TypeName)."</b>.";
    4637                             }
    4638                         }
    4639                         elsif($Kind eq "Renamed_Constant_Field")
    4640                         {
    4641                             if($Level eq "Binary") {
    4642                                 $Change = "Field <b>$Target</b> (".htmlSpecChars($Field_Type).") with the compile-time constant value <b>$Field_Value</b> has been renamed to <b>".htmlSpecChars($New_Value)."</b>.";
    4643                                 $Effect = "A client program may change behavior.";
    4644                             }
    4645                             else {
    4646                                 $Change = "Field <b>$Target</b> has been renamed to <b>".htmlSpecChars($New_Value)."</b>.";
    4647                                 $Effect = "Recompilation of a client program may be terminated with the message: cannot find variable <b>$Target</b> in <b>".htmlSpecChars($TypeName)."</b>.";
    4648                             }
    4649                         }
    4650                         elsif($Kind eq "Removed_NonConstant_Field")
    4651                         {
    4652                             $Change = "Field <b>$Target</b> of type ".htmlSpecChars($Field_Type)." has been removed from this $Type_Type.";
    4653                             if($Level eq "Binary") {
    4654                                 $Effect = "A client program may be interrupted by <b>NoSuchFieldError</b> exception.";
    4655                             }
    4656                             else {
    4657                                 $Effect = "Recompilation of a client program may be terminated with the message: cannot find variable <b>$Target</b> in <b>".htmlSpecChars($TypeName)."</b>.";
    4658                             }
    4659                         }
    4660                         elsif($Kind eq "Removed_Constant_Field")
    4661                         {
    4662                             $Change = "Field <b>$Target</b> (".htmlSpecChars($Field_Type).") with the compile-time constant value <b>$Field_Value</b> has been removed from this $Type_Type.";
    4663                             if($Level eq "Binary") {
    4664                                 $Effect = "A client program may change behavior.";
    4665                             }
    4666                             else {
    4667                                 $Effect = "Recompilation of a client program may be terminated with the message: cannot find variable <b>$Target</b> in <b>".htmlSpecChars($TypeName)."</b>.";
    4668                             }
    4669                         }
    4670                         elsif($Kind eq "Changed_Field_Type")
    4671                         {
    4672                             $Change = "Type of field <b>$Target</b> has been changed from <span class='nowrap'><b>".htmlSpecChars($Old_Value)."</b></span> to <span class='nowrap'><b>".htmlSpecChars($New_Value)."</b></span>.";
    4673                             if($Level eq "Binary") {
    4674                                 $Effect = "A client program may be interrupted by <b>NoSuchFieldError</b> exception.";
    4675                             }
    4676                             else {
    4677                                 $Effect = "Recompilation of a client program may be terminated with the message: incompatible types, found: <b>".htmlSpecChars($Old_Value)."</b>, required: <b>".htmlSpecChars($New_Value)."</b>.";
    4678                             }
    4679                         }
    4680                         elsif($Kind eq "Changed_Field_Access")
    4681                         {
    4682                             $Change = "Access level of field <b>$Target</b> has been changed from <span class='nowrap'><b>$Old_Value</b></span> to <span class='nowrap'><b>$New_Value</b></span>.";
    4683                             if($Level eq "Binary") {
    4684                                 $Effect = "A client program may be interrupted by <b>IllegalAccessError</b> exception.";
    4685                             }
    4686                             else
    4687                             {
    4688                                 if($New_Value eq "package-private") {
    4689                                     $Effect = "Recompilation of a client program may be terminated with the message: <b>$Target</b> is not public in <b>".htmlSpecChars($TypeName)."</b>; cannot be accessed from outside package.";
    4690                                 }
    4691                                 else {
    4692                                     $Effect = "Recompilation of a client program may be terminated with the message: <b>$Target</b> has <b>$New_Value</b> access in <b>".htmlSpecChars($TypeName)."</b>.";
    4693                                 }
    4694                             }
    4695                         }
    4696                         elsif($Kind eq "Changed_Final_Field_Value")
    4697                         { # Binary Only
    4698                             $Change = "Value of final field <b>$Target</b> (<b>$Field_Type</b>) has been changed from <span class='nowrap'><b>".htmlSpecChars($Old_Value)."</b></span> to <span class='nowrap'><b>".htmlSpecChars($New_Value)."</b></span>.";
    4699                             $Effect = "Old value of the field will be inlined to the client code at compile-time and will be used instead of a new one.";
    4700                         }
    4701                         elsif($Kind eq "Changed_Final_Version_Field_Value")
    4702                         { # Binary Only
    4703                             $Change = "Value of final field <b>$Target</b> (<b>$Field_Type</b>) has been changed from <span class='nowrap'><b>".htmlSpecChars($Old_Value)."</b></span> to <span class='nowrap'><b>".htmlSpecChars($New_Value)."</b></span>.";
    4704                             $Effect = "Old value of the field will be inlined to the client code at compile-time and will be used instead of a new one.";
    4705                         }
    4706                         elsif($Kind eq "Field_Became_Final")
    4707                         {
    4708                             $Change = "Field <b>$Target</b> became <b>final</b>.";
    4709                             if($Level eq "Binary") {
    4710                                 $Effect = "A client program may be interrupted by <b>IllegalAccessError</b> exception when attempt to assign new values to the field.";
    4711                             }
    4712                             else {
    4713                                 $Effect = "Recompilation of a client program may be terminated with the message: cannot assign a value to final variable $Target.";
    4714                             }
    4715                         }
    4716                         elsif($Kind eq "Field_Became_NonFinal")
    4717                         { # Binary Only
    4718                             $Change = "Field <b>$Target</b> became <b>non-final</b>.";
    4719                             $Effect = "Old value of the field will be inlined to the client code at compile-time and will be used instead of a new one.";
    4720                         }
    4721                         elsif($Kind eq "NonConstant_Field_Became_Static")
    4722                         { # Binary Only
    4723                             $Change = "Non-final field <b>$Target</b> became <b>static</b>.";
    4724                             $Effect = "A client program may be interrupted by <b>IncompatibleClassChangeError</b> exception.";
    4725                         }
    4726                         elsif($Kind eq "NonConstant_Field_Became_NonStatic")
    4727                         {
    4728                             if($Level eq "Binary") {
    4729                                 $Change = "Non-constant field <b>$Target</b> became <b>non-static</b>.";
    4730                                 $Effect = "A client program may be interrupted by <b>IncompatibleClassChangeError</b> exception.";
    4731                             }
    4732                             else {
    4733                                 $Change = "Field <b>$Target</b> became <b>non-static</b>.";
    4734                                 $Effect = "Recompilation of a client program may be terminated with the message: non-static variable <b>$Target</b> cannot be referenced from a static context.";
    4735                             }
    4736                         }
    4737                         elsif($Kind eq "Constant_Field_Became_NonStatic")
    4738                         { # Source Only
    4739                             $Change = "Field <b>$Target</b> became <b>non-static</b>.";
    4740                             $Effect = "Recompilation of a client program may be terminated with the message: non-static variable <b>$Target</b> cannot be referenced from a static context.";
    4741                         }
    4742                         elsif($Kind eq "Class_Became_Interface")
    4743                         {
    4744                             $Change = "This <b>class</b> became <b>interface</b>.";
    4745                             if($Level eq "Binary") {
    4746                                 $Effect = "A client program may be interrupted by <b>IncompatibleClassChangeError</b> or <b>InstantiationError</b> exception dependent on the usage of this class.";
    4747                             }
    4748                             else {
    4749                                 $Effect = "Recompilation of a client program may be terminated with the message: <b>".htmlSpecChars($TypeName)."</b> is abstract; cannot be instantiated.";
    4750                             }
    4751                         }
    4752                         elsif($Kind eq "Interface_Became_Class")
    4753                         {
    4754                             $Change = "This <b>interface</b> became <b>class</b>.";
    4755                             if($Level eq "Binary") {
    4756                                 $Effect = "A client program may be interrupted by <b>IncompatibleClassChangeError</b> exception.";
    4757                             }
    4758                             else {
    4759                                 $Effect = "Recompilation of a client program may be terminated with the message: interface expected.";
    4760                             }
    4761                         }
    4762                         elsif($Kind eq "Class_Became_Final")
    4763                         {
    4764                             $Change = "This class became <b>final</b>.";
    4765                             if($Level eq "Binary") {
    4766                                 $Effect = "A client program may be interrupted by <b>VerifyError</b> exception.";
    4767                             }
    4768                             else {
    4769                                 $Effect = "Recompilation of a client program may be terminated with the message: cannot inherit from final <b>".htmlSpecChars($TypeName)."</b>.";
    4770                             }
    4771                         }
    4772                         elsif($Kind eq "Class_Became_Abstract")
    4773                         {
    4774                             $Change = "This class became <b>abstract</b>.";
    4775                             if($Level eq "Binary") {
    4776                                 $Effect = "A client program may be interrupted by <b>InstantiationError</b> exception.";
    4777                             }
    4778                             else {
    4779                                 $Effect = "Recompilation of a client program may be terminated with the message: <b>".htmlSpecChars($TypeName)."</b> is abstract; cannot be instantiated.";
    4780                             }
    4781                         }
    4782                         elsif($Kind eq "Removed_Class")
    4783                         {
    4784                             $Change = "This class has been removed.";
    4785                             if($Level eq "Binary") {
    4786                                 $Effect = "A client program may be interrupted by <b>NoClassDefFoundError</b> exception.";
    4787                             }
    4788                             else {
    4789                                 $Effect = "Recompilation of a client program may be terminated with the message: cannot find class <b>".htmlSpecChars($TypeName)."</b>.";
    4790                             }
    4791                         }
    4792                         elsif($Kind eq "Removed_Interface")
    4793                         {
    4794                             $Change = "This interface has been removed.";
    4795                             if($Level eq "Binary") {
    4796                                 $Effect = "A client program may be interrupted by <b>NoClassDefFoundError</b> exception.";
    4797                             }
    4798                             else {
    4799                                 $Effect = "Recompilation of a client program may be terminated with the message: cannot find class <b>".htmlSpecChars($TypeName)."</b>.";
    4800                             }
    4801                         }
    4802                         elsif($Kind eq "Removed_Annotation")
    4803                         {
    4804                             $Change = "This annotation type has been removed.";
    4805                             if($Level eq "Binary") {
    4806                                 $Effect = "No effect.";
    4807                             }
    4808                             else {
    4809                                 $Effect = "Recompilation of a client program may be terminated with the error message: cannot find symbol <b>\@".htmlSpecChars($TypeName)."</b>.";
    4810                             }
    4811                         }
    4812                         if($Change)
    4813                         {
    4814                             $TYPE_REPORT .= "<tr><th>$ProblemNum</th><td>".$Change."</td><td>".$Effect."</td></tr>\n";
     3237                            my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, $ProblemAttr, \%AddAttr);
     3238                           
     3239                            $TYPE_REPORT .= "<tr>\n<th>$ProblemNum</th>\n<td>".$Change."</td>\n<td>".$Effect."</td>\n</tr>\n";
    48153240                            $ProblemNum += 1;
    48163241                            $ProblemsNum += 1;
    4817                             $Kinds_Locations{$Kind}{$Location} = 1;
    48183242                        }
    48193243                    }
     
    48273251                    }
    48283252                   
    4829                     my $ShowType = $TypeName;
     3253                    my $ShowType = showType($TypeName, 1, 1);
    48303254                    if($NameSpace)
    48313255                    {
    4832                         $TYPE_REPORT = cut_Namespace($TYPE_REPORT, $NameSpace);
    4833                         $ShowType = cut_Namespace($ShowType, $NameSpace);
    4834                         $Affected = cut_Namespace($Affected, $NameSpace);
     3256                        $TYPE_REPORT = cutNs($TYPE_REPORT, $NameSpace);
     3257                        $ShowType = cutNs($ShowType, $NameSpace);
     3258                        $Affected = cutNs($Affected, $NameSpace);
    48353259                    }
    48363260                   
    4837                     $TYPE_PROBLEMS .= $ContentSpanStart."<span class='ext'>[+]</span> ".htmlSpecChars($ShowType);
    4838                     if($OldStyle) {
     3261                    $TYPE_PROBLEMS .= $ContentSpanStart."<span class='ext'>[+]</span> ".$ShowType;
     3262                    if($In::Opt{"OldStyle"}) {
    48393263                        $TYPE_PROBLEMS .= " ($ProblemNum)";
    48403264                    }
     
    48613285            $Title = "Other Changes in Data Types";
    48623286        }
    4863         if($OldStyle) {
     3287        if($In::Opt{"OldStyle"}) {
    48643288            $TYPE_PROBLEMS = "<h2>$Title ($ProblemsNum)</h2><hr/>\n".$TYPE_PROBLEMS;
    48653289        }
     
    48673291            $TYPE_PROBLEMS = "<h2>$Title <span".getStyle("T", $TargetSeverity, $ProblemsNum).">&nbsp;$ProblemsNum&nbsp;</span></h2><hr/>\n".$TYPE_PROBLEMS;
    48683292        }
    4869         $TYPE_PROBLEMS = "<a name='".get_Anchor("Type", $Level, $TargetSeverity)."'></a>\n".$TYPE_PROBLEMS;
     3293        $TYPE_PROBLEMS = "<a name='".getAnchor("Type", $Level, $TargetSeverity)."'></a>\n".$TYPE_PROBLEMS;
    48703294        $TYPE_PROBLEMS .= $TOP_REF."<br/>\n";
    48713295    }
     
    48733297}
    48743298
    4875 sub cut_Namespace($$)
     3299sub cutNs($$)
    48763300{
    48773301    my ($N, $Ns) = @_;
     
    48853309   
    48863310    my $LIMIT = 10;
    4887     if(defined $AffectLimit) {
    4888         $LIMIT = $AffectLimit;
    4889     }
    4890    
    4891     my @Kinds = sort keys(%{$Kinds_Locations});
    4892     my %KLocs = ();
    4893     foreach my $Kind (@Kinds)
    4894     {
    4895         my @Locs = sort {$a=~/retval/ cmp $b=~/retval/} sort {length($a)<=>length($b)} sort keys(%{$Kinds_Locations->{$Kind}});
    4896         $KLocs{$Kind} = \@Locs;
    4897     }
    4898    
    4899     my %SymLocKind = ();
    4900     foreach my $Method (sort keys(%{$TypeProblemsIndex{$Target_TypeName}}))
    4901     {
    4902         if($Method eq ".client_method") {
    4903             next;
    4904         }
    4905        
    4906         foreach my $Kind (@Kinds)
    4907         {
    4908             foreach my $Loc (@{$KLocs{$Kind}})
    4909             {
    4910                 if(not defined $CompatProblems{$Method}{$Kind}{$Loc}) {
     3311    if(defined $In::Opt{"AffectLimit"}) {
     3312        $LIMIT = $In::Opt{"AffectLimit"};
     3313    }
     3314   
     3315    my %SymSel = ();
     3316   
     3317    foreach my $Kind (sort keys(%{$Kinds_Locations}))
     3318    {
     3319        my @Locs = sort {(index($a, "retval")!=-1) cmp (index($b, "retval")!=-1)} sort {length($a)<=>length($b)} sort keys(%{$Kinds_Locations->{$Kind}});
     3320       
     3321        foreach my $Loc (@Locs)
     3322        {
     3323            foreach my $Method (keys(%{$TypeProblemsIndex{$Level}{$Target_TypeName}{$Kind}{$Loc}}))
     3324            {
     3325                if($Method eq ".client_method") {
    49113326                    next;
    49123327                }
    49133328               
    4914                 my $Type_Name = $CompatProblems{$Method}{$Kind}{$Loc}{"Type_Name"};
    4915                 if($Type_Name ne $Target_TypeName) {
    4916                     next;
    4917                 }
    4918                
    4919                 $SymLocKind{$Method}{$Loc}{$Kind} = 1;
    4920                 last;
    4921             }
    4922         }
    4923     }
    4924    
    4925     %KLocs = (); # clear
    4926    
    4927     if(not keys(%SymLocKind)) {
     3329                if(not defined $SymSel{$Method})
     3330                {
     3331                    $SymSel{$Method}{"Kind"} = $Kind;
     3332                    $SymSel{$Method}{"Loc"} = $Loc;
     3333                }
     3334            }
     3335        }
     3336    }
     3337   
     3338    my $Total = keys(%SymSel);
     3339   
     3340    if(not $Total) {
    49283341        return "";
    49293342    }
    49303343   
    4931     my %SymSel = ();
    4932     my $Num = 0;
    4933     foreach my $Method (sort keys(%SymLocKind))
    4934     {
    4935         LOOP: foreach my $Loc (sort {$a=~/retval/ cmp $b=~/retval/} sort {length($a)<=>length($b)} sort keys(%{$SymLocKind{$Method}}))
    4936         {
    4937             foreach my $Kind (sort keys(%{$SymLocKind{$Method}{$Loc}}))
    4938             {
    4939                 $SymSel{$Method}{"Loc"} = $Loc;
    4940                 $SymSel{$Method}{"Kind"} = $Kind;
    4941                 last LOOP;
    4942             }
    4943         }
    4944        
    4945         $Num += 1;
    4946        
    4947         if($Num>=$LIMIT) {
    4948             last;
    4949         }
    4950     }
    4951    
    49523344    my $Affected = "";
     3345    my $SNum = 0;
    49533346   
    49543347    foreach my $Method (sort {lc($a) cmp lc($b)} keys(%SymSel))
     
    49613354        my $Pos = getParamPos($PName, $Method, 1);
    49623355       
    4963         $Affected .= "<span class='iname_a'>".get_Signature($Method, 1, "HTML|Italic|Param|Class|Target=".$Pos)."</span><br/>";
     3356        $Affected .= "<span class='iname_a'>".getSignature($Method, 1, "HTML|Italic|Param|Class|Target=".$Pos)."</span><br/>";
    49643357        $Affected .= "<div class='affect'>".$Desc."</div>\n";
    4965     }
    4966    
    4967     if(keys(%SymLocKind)>$LIMIT) {
     3358       
     3359        if(++$SNum>=$LIMIT) {
     3360            last;
     3361        }
     3362    }
     3363   
     3364    if($Total>$LIMIT) {
    49683365        $Affected .= " <b>...</b>\n<br/>\n"; # and others ...
    49693366    }
     
    49723369    if($Affected)
    49733370    {
    4974         my $Num = keys(%SymLocKind);
    4975         my $Per = show_number($Num*100/keys(%CheckedMethods));
     3371        my $Per = showNum($Total*100/keys(%CheckedMethods));
    49763372        $Affected =  $ContentDivStart.$Affected.$ContentDivEnd;
    4977         $Affected =  $ContentSpanStart_Affected."[+] affected methods: $Num ($Per\%)".$ContentSpanEnd.$Affected;
    4978     }
    4979    
    4980     return ($Affected);
     3373        $Affected =  $ContentSpanStart_Affected."[+] affected methods: $Total ($Per\%)".$ContentSpanEnd.$Affected;
     3374    }
     3375   
     3376    return $Affected;
    49813377}
    49823378
     
    49913387    $Location=~s/\.[^.]+?\Z//;
    49923388   
    4993     my %TypeAttr = get_Type($MethodInfo{1}{$Method}{"Class"}, 1);
    4994     my $Type_Type = $TypeAttr{"Type"};
     3389    my $TypeAttr = getType($MethodInfo{1}{$Method}{"Class"}, 1);
     3390    my $Type_Type = $TypeAttr->{"Type"};
    49953391   
    49963392    my $ABSTRACT_M = $MethodInfo{1}{$Method}{"Abstract"}?" abstract":"";
    4997     my $ABSTRACT_C = $TypeAttr{"Abstract"}?" abstract":"";
     3393    my $ABSTRACT_C = $TypeAttr->{"Abstract"}?" abstract":"";
    49983394    my $METHOD_TYPE = $MethodInfo{1}{$Method}{"Constructor"}?"constructor":"method";
    49993395   
    50003396    if($Kind eq "Class_Overridden_Method" or $Kind eq "Class_Method_Moved_Up_Hierarchy") {
    5001         return "Method '".highLight_Signature($New_Value, 2)."' will be called instead of this method in a client program.";
    5002     }
    5003     elsif($TypeProblems_Kind{$Level}{$Kind})
     3397        return "Method '".getSignature($New_Value, 2, "Class|HTML|Italic")."' will be called instead of this method in a client program.";
     3398    }
     3399    elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
    50043400    {
    50053401        my %MInfo = %{$MethodInfo{1}{$Method}};
    50063402       
    50073403        if($Location eq "this") {
    5008             return "This$ABSTRACT_M $METHOD_TYPE is from \'".htmlSpecChars($Type_Name)."\'$ABSTRACT_C $Type_Type.";
     3404            return "This$ABSTRACT_M $METHOD_TYPE is from \'".specChars($Type_Name)."\'$ABSTRACT_C $Type_Type.";
    50093405        }
    50103406       
     
    50143410        { # return value
    50153411            if($Location=~/\./) {
    5016                 push(@Sentence_Parts, "Field \'".htmlSpecChars($Location)."\' in return value");
     3412                push(@Sentence_Parts, "Field \'".specChars($Location)."\' in the return value");
    50173413            }
    50183414            else {
     
    50243420        elsif($Location=~/this/)
    50253421        { # "this" reference
    5026             push(@Sentence_Parts, "Field \'".htmlSpecChars($Location)."\' in the object");
     3422            push(@Sentence_Parts, "Field \'".specChars($Location)."\' in the object");
    50273423           
    50283424            $TypeID = $MInfo{"Class"};
     
    50343430           
    50353431            if($Location=~/\./) {
    5036                 push(@Sentence_Parts, "Field \'".htmlSpecChars($Location)."\' in ".showPos($PPos)." parameter");
     3432                push(@Sentence_Parts, "Field \'".specChars($Location)."\' in ".showPos($PPos)." parameter");
    50373433            }
    50383434            else {
     
    50583454       
    50593455        if($TypeInfo{1}{$TypeID_Problem}{"Name"} eq $Type_Name) {
    5060             push(@Sentence_Parts, "has type \'".htmlSpecChars($Type_Name)."\'.");
     3456            push(@Sentence_Parts, "is of type \'".specChars($Type_Name)."\'.");
    50613457        }
    50623458        else {
    5063             push(@Sentence_Parts, "has base type \'".htmlSpecChars($Type_Name)."\'.");
     3459            push(@Sentence_Parts, "has base type \'".specChars($Type_Name)."\'.");
    50643460        }
    50653461    }
     
    50693465sub getParamPos($$$)
    50703466{
    5071     my ($Name, $Method, $LibVersion) = @_;
    5072    
    5073     if(defined $MethodInfo{$LibVersion}{$Method}
    5074     and defined $MethodInfo{$LibVersion}{$Method}{"Param"})
    5075     {
    5076         my $Info = $MethodInfo{$LibVersion}{$Method};
     3467    my ($Name, $Method, $LVer) = @_;
     3468   
     3469    if(defined $MethodInfo{$LVer}{$Method}
     3470    and defined $MethodInfo{$LVer}{$Method}{"Param"})
     3471    {
     3472        my $Info = $MethodInfo{$LVer}{$Method};
    50773473        foreach (keys(%{$Info->{"Param"}}))
    50783474        {
     
    50963492sub getFieldType($$$)
    50973493{
    5098     my ($Location, $TypeId, $LibVersion) = @_;
     3494    my ($Location, $TypeId, $LVer) = @_;
    50993495   
    51003496    my @Fields = split(/\./, $Location);
     
    51023498    foreach my $Name (@Fields)
    51033499    {
    5104         my %Info = get_BaseType($TypeId, $LibVersion);
    5105        
    5106         foreach my $N (keys(%{$Info{"Fields"}}))
     3500        my $TInfo = getBaseType($TypeId, $LVer);
     3501       
     3502        foreach my $N (keys(%{$TInfo->{"Fields"}}))
    51073503        {
    51083504            if($N eq $Name)
    51093505            {
    5110                 $TypeId = $Info{"Fields"}{$N}{"Type"};
     3506                $TypeId = $TInfo->{"Fields"}{$N}{"Type"};
    51113507                last;
    51123508            }
     
    51243520}
    51253521
    5126 sub getRelPath($$)
    5127 {
    5128     my ($A, $B) = @_;
    5129     return abs2rel($A, get_dirname($B));
    5130 }
    5131 
    51323522sub createReport()
    51333523{
    5134     if($JoinReport)
    5135     { # --stdout
     3524    if($In::Opt{"JoinReport"}) {
    51363525        writeReport("Join", getReport("Join"));
    51373526    }
    5138     elsif($DoubleReport)
     3527    elsif($In::Opt{"DoubleReport"})
    51393528    { # default
    51403529        writeReport("Binary", getReport("Binary"));
    51413530        writeReport("Source", getReport("Source"));
    51423531    }
    5143     elsif($BinaryOnly)
     3532    elsif($In::Opt{"BinaryOnly"})
    51443533    { # --binary
    51453534        writeReport("Binary", getReport("Binary"));
    51463535    }
    5147     elsif($SourceOnly)
     3536    elsif($In::Opt{"SourceOnly"})
    51483537    { # --source
    51493538        writeReport("Source", getReport("Source"));
     
    51513540}
    51523541
    5153 sub getCssStyles()
    5154 {
    5155     my $CssStyles = "
    5156     body {
    5157         font-family:Arial, sans-serif;
    5158         background-color:White;
    5159         color:Black;
    5160     }
    5161     hr {
    5162         color:Black;
    5163         background-color:Black;
    5164         height:1px;
    5165         border:0;
    5166     }
    5167     h1 {
    5168         margin-bottom:0px;
    5169         padding-bottom:0px;
    5170         font-size:1.625em;
    5171     }
    5172     h2 {
    5173         margin-bottom:0px;
    5174         padding-bottom:0px;
    5175         font-size:1.25em;
    5176         white-space:nowrap;
    5177     }
    5178     div.symbols {
    5179         color:#003E69;
    5180     }
    5181     div.symbols i {
    5182         color:Brown;
    5183     }
    5184     span.section {
    5185         font-weight:bold;
    5186         cursor:pointer;
    5187         color:#003E69;
    5188         white-space:nowrap;
    5189         margin-left:5px;
    5190     }
    5191     span:hover.section {
    5192         color:#336699;
    5193     }
    5194     span.sect_aff {
    5195         cursor:pointer;
    5196         margin-left:7px;
    5197         padding-left:15px;
    5198         font-size:0.875em;
    5199         color:#cc3300;
    5200     }
    5201     span.ext {
    5202         font-weight:100;
    5203     }
    5204     span.jar {
    5205         color:#cc3300;
    5206         font-size:0.875em;
    5207         font-weight:bold;
    5208     }
    5209     div.jar_list {
    5210         padding-left:5px;
    5211         font-size:0.94em;
    5212     }
    5213     span.pkg_t {
    5214         color:#408080;
    5215         font-size:0.875em;
    5216     }
    5217     span.pkg {
    5218         color:#408080;
    5219         font-size:0.875em;
    5220         font-weight:bold;
    5221     }
    5222     span.cname {
    5223         color:Green;
    5224         font-size:0.875em;
    5225         font-weight:bold;
    5226     }
    5227     span.iname_b {
    5228         font-weight:bold;
    5229         font-size:1.1em;
    5230     }
    5231     span.iname_a {
    5232         color:#333333;
    5233         font-weight:bold;
    5234         font-size:0.94em;
    5235     }
    5236     span.sym_p {
    5237         font-weight:normal;
    5238         white-space:normal;
    5239     }
    5240     span.sym_p span {
    5241         white-space:nowrap;
    5242     }
    5243     span.attr {
    5244         color:Black;
    5245         font-weight:100;
    5246     }
    5247     span.deprecated {
    5248         color:Red;
    5249         font-weight:bold;
    5250         font-family:Monaco, monospace;
    5251     }
    5252     div.affect {
    5253         padding-left:15px;
    5254         padding-bottom:10px;
    5255         font-size:0.87em;
    5256         font-style:italic;
    5257         line-height:0.75em;
    5258     }
    5259     div.affected {
    5260         padding-left:30px;
    5261         padding-top:10px;
    5262     }
    5263     table.ptable {
    5264         border-collapse:collapse;
    5265         border:1px outset black;
    5266         line-height:1em;
    5267         margin-left:15px;
    5268         margin-top:3px;
    5269         margin-bottom:3px;
    5270         width:900px;
    5271     }
    5272     table.ptable td {
    5273         border:1px solid Gray;
    5274         padding: 3px;
    5275         font-size:0.875em;
    5276         text-align:left;
    5277         vertical-align:top;
    5278     }
    5279     table.ptable th {
    5280         background-color:#eeeeee;
    5281         font-weight:bold;
    5282         color:#333333;
    5283         font-family:Verdana, Arial;
    5284         font-size:0.875em;
    5285         border:1px solid Gray;
    5286         text-align:center;
    5287         vertical-align:top;
    5288         white-space:nowrap;
    5289         padding: 3px;
    5290     }
    5291     table.summary {
    5292         border-collapse:collapse;
    5293         border:1px outset black;
    5294     }
    5295     table.summary th {
    5296         background-color:#eeeeee;
    5297         font-weight:100;
    5298         text-align:left;
    5299         font-size:0.94em;
    5300         white-space:nowrap;
    5301         border:1px inset Gray;
    5302         padding: 3px;
    5303     }
    5304     table.summary td {
    5305         text-align:right;
    5306         white-space:nowrap;
    5307         border:1px inset Gray;
    5308         padding: 3px 5px 3px 10px;
    5309     }
    5310     span.mngl {
    5311         padding-left:15px;
    5312         font-size:0.875em;
    5313         cursor:text;
    5314         color:#444444;
    5315     }
    5316     span.color_p {
    5317         font-style:italic;
    5318         color:Brown;
    5319     }
    5320     span.param {
    5321         font-style:italic;
    5322     }
    5323     span.focus_p {
    5324         font-style:italic;
    5325         background-color:#DCDCDC;
    5326     }
    5327     span.nowrap {
    5328         white-space:nowrap;
    5329     }
    5330     .passed {
    5331         background-color:#CCFFCC;
    5332         font-weight:100;
    5333     }
    5334     .warning {
    5335         background-color:#F4F4AF;
    5336         font-weight:100;
    5337     }
    5338     .failed {
    5339         background-color:#FFCCCC;
    5340         font-weight:100;
    5341     }
    5342     .new {
    5343         background-color:#C6DEFF;
    5344         font-weight:100;
    5345     }
    5346    
    5347     .compatible {
    5348         background-color:#CCFFCC;
    5349         font-weight:100;
    5350     }
    5351     .almost_compatible {
    5352         background-color:#FFDAA3;
    5353         font-weight:100;
    5354     }
    5355     .incompatible {
    5356         background-color:#FFCCCC;
    5357         font-weight:100;
    5358     }
    5359     .gray {
    5360         background-color:#DCDCDC;
    5361         font-weight:100;
    5362     }
    5363    
    5364     .top_ref {
    5365         font-size:0.69em;
    5366     }
    5367     .footer {
    5368         font-size:0.75em;
    5369     }";
    5370    
    5371     if($JoinReport or $ExternCss)
    5372     {
    5373         $CssStyles .= "
    5374     .tabset {
    5375         float:left;
    5376     }
    5377     a.tab {
    5378         border:1px solid Black;
    5379         float:left;
    5380         margin:0px 5px -1px 0px;
    5381         padding:3px 5px 3px 5px;
    5382         position:relative;
    5383         font-size:0.875em;
    5384         background-color:#DDD;
    5385         text-decoration:none;
    5386         color:Black;
    5387     }
    5388     a.disabled:hover
    5389     {
    5390         color:Black;
    5391         background:#EEE;
    5392     }
    5393     a.active:hover
    5394     {
    5395         color:Black;
    5396         background:White;
    5397     }
    5398     a.active {
    5399         border-bottom-color:White;
    5400         background-color:White;
    5401     }
    5402     div.tab {
    5403         border-top:1px solid Black;
    5404         padding:0px;
    5405         width:100%;
    5406         clear:both;
    5407     }";
     3542sub getCssStyles($)
     3543{
     3544    my $Level = $_[0];
     3545   
     3546    my $CssStyles = readModule("Css", "Report.css");
     3547   
     3548    if($Level eq "Join" or $In::Opt{"ExternCss"}) {
     3549        $CssStyles .= readModule("Css", "Tabs.css");
    54083550    }
    54093551   
     
    54113553}
    54123554
    5413 sub getJsScript()
    5414 {
    5415     my $JScripts = "
    5416     function sC(header, id)
    5417     {
    5418         e = document.getElementById(id);
    5419         if(e.style.display == 'none')
    5420         {
    5421             e.style.display = 'block';
    5422             e.style.visibility = 'visible';
    5423             header.innerHTML = header.innerHTML.replace(/\\\[[^0-9 ]\\\]/gi,\"[&minus;]\");
    5424         }
    5425         else
    5426         {
    5427             e.style.display = 'none';
    5428             e.style.visibility = 'hidden';
    5429             header.innerHTML = header.innerHTML.replace(/\\\[[^0-9 ]\\\]/gi,\"[+]\");
    5430         }
    5431     }";
    5432    
    5433     if($JoinReport or $ExternJs)
    5434     {
    5435         $JScripts .= "
    5436     function initTabs()
    5437     {
    5438         var url = window.location.href;
    5439         if(url.indexOf('_Source_')!=-1 || url.indexOf('#Source')!=-1)
    5440         {
    5441             var tab1 = document.getElementById('BinaryID');
    5442             var tab2 = document.getElementById('SourceID');
    5443             tab1.className='tab disabled';
    5444             tab2.className='tab active';
    5445         }
    5446         var sets = document.getElementsByTagName('div');
    5447         for (var i = 0; i < sets.length; i++)
    5448         {
    5449             if (sets[i].className.indexOf('tabset') != -1)
    5450             {
    5451                 var tabs = [];
    5452                 var links = sets[i].getElementsByTagName('a');
    5453                 for (var j = 0; j < links.length; j++)
    5454                 {
    5455                     if (links[j].className.indexOf('tab') != -1)
    5456                     {
    5457                         tabs.push(links[j]);
    5458                         links[j].tabs = tabs;
    5459                         var tab = document.getElementById(links[j].href.substr(links[j].href.indexOf('#') + 1));
    5460                         //reset all tabs on start
    5461                         if (tab)
    5462                         {
    5463                             if (links[j].className.indexOf('active')!=-1) {
    5464                                 tab.style.display = 'block';
    5465                             }
    5466                             else {
    5467                                 tab.style.display = 'none';
    5468                             }
    5469                         }
    5470                         links[j].onclick = function()
    5471                         {
    5472                             var tab = document.getElementById(this.href.substr(this.href.indexOf('#') + 1));
    5473                             if (tab)
    5474                             {
    5475                                 //reset all tabs before change
    5476                                 for (var k = 0; k < this.tabs.length; k++)
    5477                                 {
    5478                                     document.getElementById(this.tabs[k].href.substr(this.tabs[k].href.indexOf('#') + 1)).style.display = 'none';
    5479                                     this.tabs[k].className = this.tabs[k].className.replace('active', 'disabled');
    5480                                 }
    5481                                 this.className = 'tab active';
    5482                                 tab.style.display = 'block';
    5483                                 // window.location.hash = this.id.replace('ID', '');
    5484                                 return false;
    5485                             }
    5486                         }
    5487                     }
    5488                 }
    5489             }
    5490         }
    5491         if(url.indexOf('#')!=-1) {
    5492             location.href=location.href;
    5493         }
    5494     }
    5495     if (window.addEventListener) window.addEventListener('load', initTabs, false);
    5496     else if (window.attachEvent) window.attachEvent('onload', initTabs);";
     3555sub getJsScript($)
     3556{
     3557    my $Level = $_[0];
     3558   
     3559    my $JScripts = readModule("Js", "Sections.js");
     3560   
     3561    if($Level eq "Join" or $In::Opt{"ExternJs"}) {
     3562        $JScripts .= readModule("Js", "Tabs.js");
    54973563    }
    54983564   
     
    55043570    my $Level = $_[0];
    55053571   
    5506     my $CssStyles = getCssStyles();
    5507     my $JScripts = getJsScript();
    5508    
    5509     if(defined $ExternCss)
    5510     {
    5511         $CssStyles=~s/\n    /\n/g;
    5512         writeFile($ExternCss, $CssStyles);
    5513     }
    5514    
    5515     if(defined $ExternJs)
    5516     {
    5517         $JScripts=~s/\n    /\n/g;
    5518         writeFile($ExternJs, $JScripts);
     3572    my $CssStyles = getCssStyles($Level);
     3573    my $JScripts = getJsScript($Level);
     3574   
     3575    if(defined $In::Opt{"ExternCss"}) {
     3576        writeFile($In::Opt{"ExternCss"}, $CssStyles);
     3577    }
     3578   
     3579    if(defined $In::Opt{"ExternJs"}) {
     3580        writeFile($In::Opt{"ExternJs"}, $JScripts);
    55193581    }
    55203582   
    55213583    if($Level eq "Join")
    55223584    {
    5523         my $Title = "$TargetTitle: ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
    5524         my $Keywords = "$TargetTitle, compatibility";
    5525         my $Description = "Compatibility report for the $TargetTitle library between ".$Descriptor{1}{"Version"}." and ".$Descriptor{2}{"Version"}." versions";
    5526         my ($BSummary, $BMetaData) = get_Summary("Binary");
    5527         my ($SSummary, $SMetaData) = get_Summary("Source");
     3585        my $Title = $In::Opt{"TargetTitle"}.": ".$In::Desc{1}{"Version"}." to ".$In::Desc{2}{"Version"}." compatibility report";
     3586        my $Keywords = $In::Opt{"TargetTitle"}.", compatibility";
     3587        my $Description = "Compatibility report for the ".$In::Opt{"TargetTitle"}." library between ".$In::Desc{1}{"Version"}." and ".$In::Desc{2}{"Version"}." versions";
     3588       
     3589        my ($BSummary, $BMetaData) = getSummary("Binary");
     3590        my ($SSummary, $SMetaData) = getSummary("Source");
     3591       
    55283592        my $Report = "<!-\- $BMetaData -\->\n<!-\- $SMetaData -\->\n".composeHTML_Head($Level, $Title, $Keywords, $Description, $CssStyles, $JScripts)."<body><a name='Source'></a><a name='Binary'></a><a name='Top'></a>";
    5529         $Report .= get_Report_Header("Join")."
    5530         <br/><div class='tabset'>
    5531         <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
    5532         <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
    5533         </div>";
    5534         $Report .= "<div id='BinaryTab' class='tab'>\n$BSummary\n".get_Report_Added("Binary").get_Report_Removed("Binary").get_Report_Problems("High", "Binary").get_Report_Problems("Medium", "Binary").get_Report_Problems("Low", "Binary").get_Report_Problems("Safe", "Binary").get_SourceInfo()."<br/><br/><br/></div>";
    5535         $Report .= "<div id='SourceTab' class='tab'>\n$SSummary\n".get_Report_Added("Source").get_Report_Removed("Source").get_Report_Problems("High", "Source").get_Report_Problems("Medium", "Source").get_Report_Problems("Low", "Source").get_Report_Problems("Safe", "Source").get_SourceInfo()."<br/><br/><br/></div>";
     3593       
     3594        $Report .= getReportHeader("Join");
     3595        $Report .= "<br/><div class='tabset'>\n";
     3596        $Report .= "<a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>\n";
     3597        $Report .= "<a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>\n";
     3598        $Report .= "</div>\n";
     3599       
     3600        $Report .= "<div id='BinaryTab' class='tab'>\n$BSummary\n".getReportAdded("Binary").getReportRemoved("Binary").getReportProblems("High", "Binary").getReportProblems("Medium", "Binary").getReportProblems("Low", "Binary").getReportProblems("Safe", "Binary").getSourceInfo()."<br/><br/><br/></div>";
     3601       
     3602        $Report .= "<div id='SourceTab' class='tab'>\n$SSummary\n".getReportAdded("Source").getReportRemoved("Source").getReportProblems("High", "Source").getReportProblems("Medium", "Source").getReportProblems("Low", "Source").getReportProblems("Safe", "Source").getSourceInfo()."<br/><br/><br/></div>";
     3603       
    55363604        $Report .= getReportFooter();
    55373605        $Report .= "\n</body></html>";
     
    55403608    else
    55413609    {
    5542         my ($Summary, $MetaData) = get_Summary($Level);
    5543         my $Title = "$TargetTitle: ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
    5544         my $Keywords = "$TargetTitle, ".lc($Level).", compatibility";
    5545         my $Description = "$Level compatibility report for the $TargetTitle library between ".$Descriptor{1}{"Version"}." and ".$Descriptor{2}{"Version"}." versions";
     3610        my ($Summary, $MetaData) = getSummary($Level);
     3611       
     3612        my $Title = $In::Opt{"TargetTitle"}.": ".$In::Desc{1}{"Version"}." to ".$In::Desc{2}{"Version"}." ".lc($Level)." compatibility report";
     3613        my $Keywords = $In::Opt{"TargetTitle"}.", ".lc($Level).", compatibility";
     3614        my $Description = "$Level compatibility report for the ".$In::Opt{"TargetTitle"}." library between ".$In::Desc{1}{"Version"}." and ".$In::Desc{2}{"Version"}." versions";
    55463615       
    55473616        my $Report = "<!-\- $MetaData -\->\n".composeHTML_Head($Level, $Title, $Keywords, $Description, $CssStyles, $JScripts)."<body><a name='Top'></a>";
    5548         $Report .= get_Report_Header($Level)."\n".$Summary."\n";
    5549         $Report .= get_Report_Added($Level).get_Report_Removed($Level);
    5550         $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
    5551         $Report .= get_SourceInfo()."<br/><br/><br/>\n";
     3617        $Report .= getReportHeader($Level)."\n".$Summary."\n";
     3618        $Report .= getReportAdded($Level).getReportRemoved($Level);
     3619        $Report .= getReportProblems("High", $Level).getReportProblems("Medium", $Level).getReportProblems("Low", $Level).getReportProblems("Safe", $Level);
     3620        $Report .= getSourceInfo()."<br/><br/><br/>\n";
    55523621        $Report .= getReportFooter();
    55533622        $Report .= "\n</body></html>";
     
    55673636}
    55683637
    5569 sub get_Report_Problems($$)
     3638sub getReportProblems($$)
    55703639{
    55713640    my ($Priority, $Level) = @_;
    5572     my $Report = get_Report_TypeProblems($Priority, $Level);
    5573     if(my $MProblems = get_Report_MethodProblems($Priority, $Level)) {
     3641    my $Report = getReportTypeProblems($Priority, $Level);
     3642    if(my $MProblems = getReportMethodProblems($Priority, $Level)) {
    55743643        $Report .= $MProblems;
    55753644    }
    55763645    if($Report)
    55773646    {
    5578         if($JoinReport)
     3647        if($In::Opt{"JoinReport"})
    55793648        {
    55803649            if($Priority eq "Safe") {
     
    56113680    my $RPath = getReportPath($Level);
    56123681   
    5613     if(defined $ExternCss) {
    5614         $Head .= "<link rel=\"stylesheet\" type=\"text/css\" href=\"".getRelPath($ExternCss, $RPath)."\" />\n";
    5615     }
    5616    
    5617     if(defined $ExternJs) {
    5618         $Head .= "<script type=\"text/javascript\" src=\"".getRelPath($ExternJs, $RPath)."\"></script>\n";
     3682    if(defined $In::Opt{"ExternCss"}) {
     3683        $Head .= "<link rel=\"stylesheet\" type=\"text/css\" href=\"".getRelPath($In::Opt{"ExternCss"}, $RPath)."\" />\n";
     3684    }
     3685   
     3686    if(defined $In::Opt{"ExternJs"}) {
     3687        $Head .= "<script type=\"text/javascript\" src=\"".getRelPath($In::Opt{"ExternJs"}, $RPath)."\"></script>\n";
    56193688    }
    56203689   
    56213690    $Head .= "<title>$Title</title>\n";
    56223691   
    5623     if(not defined $ExternCss) {
     3692    if(not defined $In::Opt{"ExternCss"}) {
    56243693        $Head .= "<style type=\"text/css\">\n$Styles\n</style>\n";
    56253694    }
    56263695   
    5627     if(not defined $ExternJs) {
     3696    if(not defined $In::Opt{"ExternJs"}) {
    56283697        $Head .= "<script type=\"text/javascript\" language=\"JavaScript\">\n<!--\n$Scripts\n-->\n</script>\n";
    56293698    }
    56303699   
    56313700    $Head .= "</head>\n";
    5632    
    5633     $Head=~s/\n    /\n/g;
    56343701   
    56353702    return $Head;
     
    56523719}
    56533720
    5654 sub readArchives($)
    5655 {
    5656     my $LibVersion = $_[0];
    5657     my @ArchivePaths = getArchives($LibVersion);
    5658     if($#ArchivePaths==-1) {
    5659         exitStatus("Error", "Java ARchives are not found in ".$Descriptor{$LibVersion}{"Version"});
    5660     }
    5661     printMsg("INFO", "reading classes ".$Descriptor{$LibVersion}{"Version"}." ...");
    5662     $TYPE_ID = 0;
    5663    
    5664     foreach my $ArchivePath (sort {length($a)<=>length($b)} @ArchivePaths) {
    5665         readArchive($LibVersion, $ArchivePath);
    5666     }
    5667     foreach my $TName (keys(%{$TName_Tid{$LibVersion}}))
    5668     {
    5669         my $Tid = $TName_Tid{$LibVersion}{$TName};
    5670         if(not $TypeInfo{$LibVersion}{$Tid}{"Type"})
    5671         {
    5672             if($TName=~/\A(void|boolean|char|byte|short|int|float|long|double)\Z/) {
    5673                 $TypeInfo{$LibVersion}{$Tid}{"Type"} = "primitive";
    5674             }
    5675             else {
    5676                 $TypeInfo{$LibVersion}{$Tid}{"Type"} = "class";
    5677             }
    5678         }
    5679     }
    5680    
    5681     foreach my $Method (keys(%{$MethodInfo{$LibVersion}}))
    5682     {
    5683         $MethodInfo{$LibVersion}{$Method}{"Signature"} = get_Signature($Method, $LibVersion, "Full");
    5684         $tr_name{$Method} = get_TypeName($MethodInfo{$LibVersion}{$Method}{"Class"}, $LibVersion).".".get_Signature($Method, $LibVersion, "Short");
    5685     }
    5686 }
    5687 
    5688 sub testSystem()
    5689 {
    5690     printMsg("INFO", "\nverifying detectable Java library changes");
    5691    
    5692     my $LibName = "libsample_java";
    5693     if(-d $LibName) {
    5694         rmtree($LibName);
    5695     }
    5696    
    5697     my $PackageName = "TestPackage";
    5698     my $Path_v1 = "$LibName/$PackageName.v1/$PackageName";
    5699     mkpath($Path_v1);
    5700    
    5701     my $Path_v2 = "$LibName/$PackageName.v2/$PackageName";
    5702     mkpath($Path_v2);
    5703    
    5704     my $TestsPath = "$LibName/Tests";
    5705     mkpath($TestsPath);
    5706    
    5707     # FirstCheckedException
    5708     my $FirstCheckedException = "package $PackageName;
    5709     public class FirstCheckedException extends Exception {
    5710     }";
    5711     writeFile($Path_v1."/FirstCheckedException.java", $FirstCheckedException);
    5712     writeFile($Path_v2."/FirstCheckedException.java", $FirstCheckedException);
    5713    
    5714     # SecondCheckedException
    5715     my $SecondCheckedException = "package $PackageName;
    5716     public class SecondCheckedException extends Exception {
    5717     }";
    5718     writeFile($Path_v1."/SecondCheckedException.java", $SecondCheckedException);
    5719     writeFile($Path_v2."/SecondCheckedException.java", $SecondCheckedException);
    5720    
    5721     # FirstUncheckedException
    5722     my $FirstUncheckedException = "package $PackageName;
    5723     public class FirstUncheckedException extends RuntimeException {
    5724     }";
    5725     writeFile($Path_v1."/FirstUncheckedException.java", $FirstUncheckedException);
    5726     writeFile($Path_v2."/FirstUncheckedException.java", $FirstUncheckedException);
    5727    
    5728     # SecondUncheckedException
    5729     my $SecondUncheckedException = "package $PackageName;
    5730     public class SecondUncheckedException extends RuntimeException {
    5731     }";
    5732     writeFile($Path_v1."/SecondUncheckedException.java", $SecondUncheckedException);
    5733     writeFile($Path_v2."/SecondUncheckedException.java", $SecondUncheckedException);
    5734    
    5735     # BaseAbstractClass
    5736     my $BaseAbstractClass = "package $PackageName;
    5737     public abstract class BaseAbstractClass {
    5738         public Integer field;
    5739         public Integer someMethod(Integer param) { return param; }
    5740         public abstract Integer abstractMethod(Integer param);
    5741     }";
    5742     writeFile($Path_v1."/BaseAbstractClass.java", $BaseAbstractClass);
    5743     writeFile($Path_v2."/BaseAbstractClass.java", $BaseAbstractClass);
    5744    
    5745     # Removed_Annotation
    5746     writeFile($Path_v1."/RemovedAnnotation.java",
    5747     "package $PackageName;
    5748     public \@interface RemovedAnnotation {
    5749     }");
    5750    
    5751     # Beta Annotation
    5752     writeFile($Path_v1."/Beta.java",
    5753     "package $PackageName;
    5754     public \@interface Beta {
    5755     }");
    5756    
    5757     writeFile($Path_v2."/Beta.java",
    5758     "package $PackageName;
    5759     public \@interface Beta {
    5760     }");
    5761    
    5762     # BaseClass
    5763     my $BaseClass = "package $PackageName;
    5764     public class BaseClass {
    5765         public Integer field;
    5766         public Integer method(Integer param) { return param; }
    5767     }";
    5768     writeFile($Path_v1."/BaseClass.java", $BaseClass);
    5769     writeFile($Path_v2."/BaseClass.java", $BaseClass);
    5770    
    5771     # BaseClass2
    5772     my $BaseClass2 = "package $PackageName;
    5773     public class BaseClass2 {
    5774         public Integer field2;
    5775         public Integer method2(Integer param) { return param; }
    5776     }";
    5777     writeFile($Path_v1."/BaseClass2.java", $BaseClass2);
    5778     writeFile($Path_v2."/BaseClass2.java", $BaseClass2);
    5779    
    5780     # BaseInterface
    5781     my $BaseInterface = "package $PackageName;
    5782     public interface BaseInterface {
    5783         public Integer field = 100;
    5784         public Integer method(Integer param);
    5785     }";
    5786     writeFile($Path_v1."/BaseInterface.java", $BaseInterface);
    5787     writeFile($Path_v2."/BaseInterface.java", $BaseInterface);
    5788    
    5789     # BaseInterface2
    5790     my $BaseInterface2 = "package $PackageName;
    5791     public interface BaseInterface2 {
    5792         public Integer field2 = 100;
    5793         public Integer method2(Integer param);
    5794     }";
    5795     writeFile($Path_v1."/BaseInterface2.java", $BaseInterface2);
    5796     writeFile($Path_v2."/BaseInterface2.java", $BaseInterface2);
    5797    
    5798     # BaseConstantInterface
    5799     my $BaseConstantInterface = "package $PackageName;
    5800     public interface BaseConstantInterface {
    5801         public Integer CONSTANT = 10;
    5802         public Integer CONSTANT2 = 100;
    5803     }";
    5804     writeFile($Path_v1."/BaseConstantInterface.java", $BaseConstantInterface);
    5805     writeFile($Path_v2."/BaseConstantInterface.java", $BaseConstantInterface);
    5806    
    5807     # Removed_Method (Beta method)
    5808     writeFile($Path_v1."/RemovedBetaMethod.java",
    5809     "package $PackageName;
    5810     public class RemovedBetaMethod
    5811     {
    5812         \@Beta
    5813         public Integer someMethod() {
    5814             return 0;
    5815         }
    5816     }");
    5817     writeFile($Path_v2."/RemovedBetaMethod.java",
    5818     "package $PackageName;
    5819     public class RemovedBetaMethod {
    5820     }");
    5821    
    5822     # Removed_Method (from Beta class)
    5823     writeFile($Path_v1."/RemovedMethodFromBetaClass.java",
    5824     "package $PackageName;
    5825     \@Beta
    5826     public class RemovedMethodFromBetaClass
    5827     {
    5828         public Integer someMethod() {
    5829             return 0;
    5830         }
    5831     }");
    5832     writeFile($Path_v2."/RemovedMethodFromBetaClass.java",
    5833     "package $PackageName;
    5834     \@Beta
    5835     public class RemovedMethodFromBetaClass {
    5836     }");
    5837    
    5838     # Removed_Class (Beta)
    5839     writeFile($Path_v1."/RemovedBetaClass.java",
    5840     "package $PackageName;
    5841     \@Beta
    5842     public class RemovedBetaClass
    5843     {
    5844         public Integer someMethod() {
    5845             return 0;
    5846         }
    5847     }");
    5848    
    5849     # Abstract_Method_Added_Checked_Exception
    5850     writeFile($Path_v1."/AbstractMethodAddedCheckedException.java",
    5851     "package $PackageName;
    5852     public abstract class AbstractMethodAddedCheckedException {
    5853         public abstract Integer someMethod() throws FirstCheckedException;
    5854     }");
    5855     writeFile($Path_v2."/AbstractMethodAddedCheckedException.java",
    5856     "package $PackageName;
    5857     public abstract class AbstractMethodAddedCheckedException {
    5858         public abstract Integer someMethod() throws FirstCheckedException, SecondCheckedException;
    5859     }");
    5860    
    5861     # Abstract_Method_Removed_Checked_Exception
    5862     writeFile($Path_v1."/AbstractMethodRemovedCheckedException.java",
    5863     "package $PackageName;
    5864     public abstract class AbstractMethodRemovedCheckedException {
    5865         public abstract Integer someMethod() throws FirstCheckedException, SecondCheckedException;
    5866     }");
    5867     writeFile($Path_v2."/AbstractMethodRemovedCheckedException.java",
    5868     "package $PackageName;
    5869     public abstract class AbstractMethodRemovedCheckedException {
    5870         public abstract Integer someMethod() throws FirstCheckedException;
    5871     }");
    5872    
    5873     # NonAbstract_Method_Added_Checked_Exception
    5874     writeFile($Path_v1."/NonAbstractMethodAddedCheckedException.java",
    5875     "package $PackageName;
    5876     public class NonAbstractMethodAddedCheckedException {
    5877         public Integer someMethod() throws FirstCheckedException {
    5878             return 10;
    5879         }
    5880     }");
    5881     writeFile($Path_v2."/NonAbstractMethodAddedCheckedException.java",
    5882     "package $PackageName;
    5883     public class NonAbstractMethodAddedCheckedException {
    5884         public Integer someMethod() throws FirstCheckedException, SecondCheckedException {
    5885             return 10;
    5886         }
    5887     }");
    5888    
    5889     # NonAbstract_Method_Removed_Checked_Exception
    5890     writeFile($Path_v1."/NonAbstractMethodRemovedCheckedException.java",
    5891     "package $PackageName;
    5892     public class NonAbstractMethodRemovedCheckedException {
    5893         public Integer someMethod() throws FirstCheckedException, SecondCheckedException {
    5894             return 10;
    5895         }
    5896     }");
    5897     writeFile($Path_v2."/NonAbstractMethodRemovedCheckedException.java",
    5898     "package $PackageName;
    5899     public class NonAbstractMethodRemovedCheckedException {
    5900         public Integer someMethod() throws FirstCheckedException {
    5901             return 10;
    5902         }
    5903     }");
    5904    
    5905     # Added_Unchecked_Exception
    5906     writeFile($Path_v1."/AddedUncheckedException.java",
    5907     "package $PackageName;
    5908     public class AddedUncheckedException {
    5909         public Integer someMethod() throws FirstUncheckedException {
    5910             return 10;
    5911         }
    5912     }");
    5913     writeFile($Path_v2."/AddedUncheckedException.java",
    5914     "package $PackageName;
    5915     public class AddedUncheckedException {
    5916         public Integer someMethod() throws FirstUncheckedException, SecondUncheckedException, NullPointerException {
    5917             return 10;
    5918         }
    5919     }");
    5920    
    5921     # Removed_Unchecked_Exception
    5922     writeFile($Path_v1."/RemovedUncheckedException.java",
    5923     "package $PackageName;
    5924     public class RemovedUncheckedException {
    5925         public Integer someMethod() throws FirstUncheckedException, SecondUncheckedException, NullPointerException {
    5926             return 10;
    5927         }
    5928     }");
    5929     writeFile($Path_v2."/RemovedUncheckedException.java",
    5930     "package $PackageName;
    5931     public class RemovedUncheckedException {
    5932         public Integer someMethod() throws FirstUncheckedException {
    5933             return 10;
    5934         }
    5935     }");
    5936    
    5937     # Changed_Method_Return_From_Void
    5938     writeFile($Path_v1."/ChangedMethodReturnFromVoid.java",
    5939     "package $PackageName;
    5940     public class ChangedMethodReturnFromVoid {
    5941         public void changedMethod(Integer param1, String[] param2) { }
    5942     }");
    5943     writeFile($Path_v2."/ChangedMethodReturnFromVoid.java",
    5944     "package $PackageName;
    5945     public class ChangedMethodReturnFromVoid {
    5946         public Integer changedMethod(Integer param1, String[] param2){
    5947             return param1;
    5948         }
    5949     }");
    5950    
    5951     # Added_Method
    5952     writeFile($Path_v1."/AddedMethod.java",
    5953     "package $PackageName;
    5954     public class AddedMethod {
    5955         public Integer field = 100;
    5956     }");
    5957     writeFile($Path_v2."/AddedMethod.java",
    5958     "package $PackageName;
    5959     public class AddedMethod {
    5960         public Integer field = 100;
    5961         public Integer addedMethod(Integer param1, String[] param2) { return param1; }
    5962         public static String[] addedStaticMethod(String[] param) { return param; }
    5963     }");
    5964    
    5965     # Added_Method (Constructor)
    5966     writeFile($Path_v1."/AddedConstructor.java",
    5967     "package $PackageName;
    5968     public class AddedConstructor {
    5969         public Integer field = 100;
    5970     }");
    5971     writeFile($Path_v2."/AddedConstructor.java",
    5972     "package $PackageName;
    5973     public class AddedConstructor {
    5974         public Integer field = 100;
    5975         public AddedConstructor() { }
    5976         public AddedConstructor(Integer x, String y) { }
    5977     }");
    5978    
    5979     # Class_Added_Field
    5980     writeFile($Path_v1."/ClassAddedField.java",
    5981     "package $PackageName;
    5982     public class ClassAddedField {
    5983         public Integer otherField;
    5984     }");
    5985     writeFile($Path_v2."/ClassAddedField.java",
    5986     "package $PackageName;
    5987     public class ClassAddedField {
    5988         public Integer addedField;
    5989         public Integer otherField;
    5990     }");
    5991    
    5992     # Interface_Added_Field
    5993     writeFile($Path_v1."/InterfaceAddedField.java",
    5994     "package $PackageName;
    5995     public interface InterfaceAddedField {
    5996         public Integer method();
    5997     }");
    5998     writeFile($Path_v2."/InterfaceAddedField.java",
    5999     "package $PackageName;
    6000     public interface InterfaceAddedField {
    6001         public Integer addedField = 100;
    6002         public Integer method();
    6003     }");
    6004    
    6005     # Removed_NonConstant_Field (Class)
    6006     writeFile($Path_v1."/ClassRemovedField.java",
    6007     "package $PackageName;
    6008     public class ClassRemovedField {
    6009         public Integer removedField;
    6010         public Integer otherField;
    6011     }");
    6012     writeFile($Path_v2."/ClassRemovedField.java",
    6013     "package $PackageName;
    6014     public class ClassRemovedField {
    6015         public Integer otherField;
    6016     }");
    6017    
    6018     writeFile($TestsPath."/Test_ClassRemovedField.java",
    6019     "import $PackageName.*;
    6020     public class Test_ClassRemovedField {
    6021         public static void main(String[] args) {
    6022             ClassRemovedField X = new ClassRemovedField();
    6023             Integer Copy = X.removedField;
    6024         }
    6025     }");
    6026    
    6027     writeFile($TestsPath."/Test_RemovedAnnotation.java",
    6028     "import $PackageName.*;
    6029     public class Test_RemovedAnnotation {
    6030         public static void main(String[] args) {
    6031             testMethod();
    6032         }
    6033        
    6034         \@RemovedAnnotation
    6035         static void testMethod() {
    6036         }
    6037     }");
    6038    
    6039     # Removed_Constant_Field (Interface)
    6040     writeFile($Path_v1."/InterfaceRemovedConstantField.java",
    6041     "package $PackageName;
    6042     public interface InterfaceRemovedConstantField {
    6043         public String someMethod();
    6044         public int removedField_Int = 1000;
    6045         public String removedField_Str = \"Value\";
    6046     }");
    6047     writeFile($Path_v2."/InterfaceRemovedConstantField.java",
    6048     "package $PackageName;
    6049     public interface InterfaceRemovedConstantField {
    6050         public String someMethod();
    6051     }");
    6052    
    6053     # Removed_NonConstant_Field (Interface)
    6054     writeFile($Path_v1."/InterfaceRemovedField.java",
    6055     "package $PackageName;
    6056     public interface InterfaceRemovedField {
    6057         public String someMethod();
    6058         public BaseClass removedField = new BaseClass();
    6059     }");
    6060     writeFile($Path_v2."/InterfaceRemovedField.java",
    6061     "package $PackageName;
    6062     public interface InterfaceRemovedField {
    6063         public String someMethod();
    6064     }");
    6065    
    6066     # Renamed_Field
    6067     writeFile($Path_v1."/RenamedField.java",
    6068     "package $PackageName;
    6069     public class RenamedField {
    6070         public String oldName;
    6071     }");
    6072     writeFile($Path_v2."/RenamedField.java",
    6073     "package $PackageName;
    6074     public class RenamedField {
    6075         public String newName;
    6076     }");
    6077    
    6078     # Renamed_Constant_Field
    6079     writeFile($Path_v1."/RenamedConstantField.java",
    6080     "package $PackageName;
    6081     public class RenamedConstantField {
    6082         public final String oldName = \"Value\";
    6083     }");
    6084     writeFile($Path_v2."/RenamedConstantField.java",
    6085     "package $PackageName;
    6086     public class RenamedConstantField {
    6087         public final String newName = \"Value\";
    6088     }");
    6089    
    6090     # Changed_Field_Type
    6091     writeFile($Path_v1."/ChangedFieldType.java",
    6092     "package $PackageName;
    6093     public class ChangedFieldType {
    6094         public String fieldName;
    6095     }");
    6096     writeFile($Path_v2."/ChangedFieldType.java",
    6097     "package $PackageName;
    6098     public class ChangedFieldType {
    6099         public Integer fieldName;
    6100     }");
    6101    
    6102     # Changed_Field_Access
    6103     writeFile($Path_v1."/ChangedFieldAccess.java",
    6104     "package $PackageName;
    6105     public class ChangedFieldAccess {
    6106         public String fieldName;
    6107     }");
    6108     writeFile($Path_v2."/ChangedFieldAccess.java",
    6109     "package $PackageName;
    6110     public class ChangedFieldAccess {
    6111         private String fieldName;
    6112     }");
    6113    
    6114     # Changed_Final_Field_Value
    6115     writeFile($Path_v1."/ChangedFinalFieldValue.java",
    6116     "package $PackageName;
    6117     public class ChangedFinalFieldValue {
    6118         public final int field = 1;
    6119         public final String field2 = \" \";
    6120     }");
    6121     writeFile($Path_v2."/ChangedFinalFieldValue.java",
    6122     "package $PackageName;
    6123     public class ChangedFinalFieldValue {
    6124         public final int field = 2;
    6125         public final String field2 = \"newValue\";
    6126     }");
    6127    
    6128     # NonConstant_Field_Became_Static
    6129     writeFile($Path_v1."/NonConstantFieldBecameStatic.java",
    6130     "package $PackageName;
    6131     public class NonConstantFieldBecameStatic {
    6132         public String fieldName;
    6133     }");
    6134     writeFile($Path_v2."/NonConstantFieldBecameStatic.java",
    6135     "package $PackageName;
    6136     public class NonConstantFieldBecameStatic {
    6137         public static String fieldName;
    6138     }");
    6139    
    6140     # NonConstant_Field_Became_NonStatic
    6141     writeFile($Path_v1."/NonConstantFieldBecameNonStatic.java",
    6142     "package $PackageName;
    6143     public class NonConstantFieldBecameNonStatic {
    6144         public static String fieldName;
    6145     }");
    6146     writeFile($Path_v2."/NonConstantFieldBecameNonStatic.java",
    6147     "package $PackageName;
    6148     public class NonConstantFieldBecameNonStatic {
    6149         public String fieldName;
    6150     }");
    6151    
    6152     # Constant_Field_Became_NonStatic
    6153     writeFile($Path_v1."/ConstantFieldBecameNonStatic.java",
    6154     "package $PackageName;
    6155     public class ConstantFieldBecameNonStatic {
    6156         public final static String fieldName = \"Value\";
    6157     }");
    6158     writeFile($Path_v2."/ConstantFieldBecameNonStatic.java",
    6159     "package $PackageName;
    6160     public class ConstantFieldBecameNonStatic {
    6161         public final String fieldName = \"Value\";
    6162     }");
    6163    
    6164     # Field_Became_Final
    6165     writeFile($Path_v1."/FieldBecameFinal.java",
    6166     "package $PackageName;
    6167     public class FieldBecameFinal {
    6168         public String fieldName;
    6169     }");
    6170     writeFile($Path_v2."/FieldBecameFinal.java",
    6171     "package $PackageName;
    6172     public class FieldBecameFinal {
    6173         public final String fieldName = \"Value\";
    6174     }");
    6175    
    6176     # Field_Became_NonFinal
    6177     writeFile($Path_v1."/FieldBecameNonFinal.java",
    6178     "package $PackageName;
    6179     public class FieldBecameNonFinal {
    6180         public final String fieldName = \"Value\";
    6181     }");
    6182     writeFile($Path_v2."/FieldBecameNonFinal.java",
    6183     "package $PackageName;
    6184     public class FieldBecameNonFinal {
    6185         public String fieldName;
    6186     }");
    6187    
    6188     # Removed_Method
    6189     writeFile($Path_v1."/RemovedMethod.java",
    6190     "package $PackageName;
    6191     public class RemovedMethod {
    6192         public Integer field = 100;
    6193         public Integer removedMethod(Integer param1, String param2) { return param1; }
    6194         public static Integer removedStaticMethod(Integer param) { return param; }
    6195     }");
    6196     writeFile($Path_v2."/RemovedMethod.java",
    6197     "package $PackageName;
    6198     public class RemovedMethod {
    6199         public Integer field = 100;
    6200     }");
    6201    
    6202     # Removed_Method (move up to java.lang.Object)
    6203     writeFile($Path_v1."/MoveUpToJavaLangObject.java",
    6204     "package $PackageName;
    6205     public class MoveUpToJavaLangObject extends java.lang.Object {
    6206         public int hashCode() { return 0; }
    6207     }");
    6208     writeFile($Path_v2."/MoveUpToJavaLangObject.java",
    6209     "package $PackageName;
    6210     public class MoveUpToJavaLangObject extends java.lang.Object {
    6211     }");
    6212    
    6213     writeFile($TestsPath."/Test_MoveUpToJavaLangObject.java",
    6214     "import $PackageName.*;
    6215     public class Test_MoveUpToJavaLangObject {
    6216         public static void main(String[] args) {
    6217             MoveUpToJavaLangObject X = new MoveUpToJavaLangObject();
    6218             int R = X.hashCode();
    6219         }
    6220     }");
    6221    
    6222     # Removed_Method (Deprecated)
    6223     writeFile($Path_v1."/RemovedDeprecatedMethod.java",
    6224     "package $PackageName;
    6225     public class RemovedDeprecatedMethod {
    6226         public Integer field = 100;
    6227         public Integer otherMethod(Integer param) { return param; }
    6228         \@Deprecated
    6229         public Integer removedMethod(Integer param1, String param2) { return param1; }
    6230     }");
    6231     writeFile($Path_v2."/RemovedDeprecatedMethod.java",
    6232     "package $PackageName;
    6233     public class RemovedDeprecatedMethod {
    6234         public Integer field = 100;
    6235         public Integer otherMethod(Integer param) { return param; }
    6236     }");
    6237    
    6238     # Interface_Removed_Abstract_Method
    6239     writeFile($Path_v1."/InterfaceRemovedAbstractMethod.java",
    6240     "package $PackageName;
    6241     public interface InterfaceRemovedAbstractMethod extends BaseInterface, BaseInterface2 {
    6242         public void removedMethod(Integer param1, java.io.ObjectOutput param2);
    6243         public void someMethod(Integer param);
    6244     }");
    6245     writeFile($Path_v2."/InterfaceRemovedAbstractMethod.java",
    6246     "package $PackageName;
    6247     public interface InterfaceRemovedAbstractMethod extends BaseInterface, BaseInterface2 {
    6248         public void someMethod(Integer param);
    6249     }");
    6250    
    6251     # Interface_Added_Abstract_Method
    6252     writeFile($Path_v1."/InterfaceAddedAbstractMethod.java",
    6253     "package $PackageName;
    6254     public interface InterfaceAddedAbstractMethod extends BaseInterface, BaseInterface2 {
    6255         public void someMethod(Integer param);
    6256     }");
    6257     writeFile($Path_v2."/InterfaceAddedAbstractMethod.java",
    6258     "package $PackageName;
    6259     public interface InterfaceAddedAbstractMethod extends BaseInterface, BaseInterface2 {
    6260         public void someMethod(Integer param);
    6261         public Integer addedMethod(Integer param);
    6262     }");
    6263    
    6264     # Interface_Added_Default_Method
    6265     writeFile($Path_v1."/InterfaceAddedDefaultMethod.java",
    6266     "package $PackageName;
    6267     public interface InterfaceAddedDefaultMethod {
    6268         public void someMethod(Integer param);
    6269     }");
    6270     writeFile($Path_v2."/InterfaceAddedDefaultMethod.java",
    6271     "package $PackageName;
    6272     public interface InterfaceAddedDefaultMethod {
    6273         public void someMethod(Integer param);
    6274         default Integer addedMethod(Integer param) { return 0; }
    6275     }");
    6276    
    6277     # Method_Became_NonDefault
    6278     writeFile($Path_v1."/MethodBecameNonDefault.java",
    6279     "package $PackageName;
    6280     public interface MethodBecameNonDefault {
    6281         default Integer someMethod(Integer param) { return 0; }
    6282     }");
    6283     writeFile($Path_v2."/MethodBecameNonDefault.java",
    6284     "package $PackageName;
    6285     public interface MethodBecameNonDefault {
    6286         public Integer someMethod(Integer param);
    6287     }");
    6288    
    6289     writeFile($TestsPath."/Test_MethodBecameNonDefault.java",
    6290     "import $PackageName.*;
    6291     class Class_MethodBecameNonDefault implements MethodBecameNonDefault {
    6292     };
    6293    
    6294     public class Test_MethodBecameNonDefault
    6295     {
    6296         public static void main(String[] args)
    6297         {
    6298             Class_MethodBecameNonDefault Obj = new Class_MethodBecameNonDefault();
    6299             Integer Res = Obj.someMethod(0);
    6300         }
    6301     }");
    6302    
    6303     # Variable_Arity_To_Array
    6304     writeFile($Path_v1."/VariableArityToArray.java",
    6305     "package $PackageName;
    6306     public class VariableArityToArray {
    6307         public void someMethod(Integer x, String... y) { };
    6308     }");
    6309     writeFile($Path_v2."/VariableArityToArray.java",
    6310     "package $PackageName;
    6311     public class VariableArityToArray {
    6312         public void someMethod(Integer x, String[] y) { };
    6313     }");
    6314    
    6315     # Class_Became_Interface
    6316     writeFile($Path_v1."/ClassBecameInterface.java",
    6317     "package $PackageName;
    6318     public class ClassBecameInterface extends BaseClass {
    6319         public Integer someMethod(Integer param) {
    6320             return param;
    6321         }
    6322     }");
    6323     writeFile($Path_v2."/ClassBecameInterface.java",
    6324     "package $PackageName;
    6325     public interface ClassBecameInterface extends BaseInterface, BaseInterface2 {
    6326         public Integer someMethod(Integer param);
    6327     }");
    6328    
    6329     # Added_Super_Class
    6330     writeFile($Path_v1."/AddedSuperClass.java",
    6331     "package $PackageName;
    6332     public class AddedSuperClass {
    6333         public Integer someMethod(Integer param) {
    6334             return param;
    6335         }
    6336     }");
    6337     writeFile($Path_v2."/AddedSuperClass.java",
    6338     "package $PackageName;
    6339     public class AddedSuperClass extends BaseClass {
    6340         public Integer someMethod(Integer param) {
    6341             return param;
    6342         }
    6343     }");
    6344    
    6345     # Abstract_Class_Added_Super_Abstract_Class
    6346     writeFile($Path_v1."/AbstractClassAddedSuperAbstractClass.java",
    6347     "package $PackageName;
    6348     public abstract class AbstractClassAddedSuperAbstractClass {
    6349         public Integer someMethod(Integer param) {
    6350             return param;
    6351         }
    6352     }");
    6353     writeFile($Path_v2."/AbstractClassAddedSuperAbstractClass.java",
    6354     "package $PackageName;
    6355     public abstract class AbstractClassAddedSuperAbstractClass extends BaseAbstractClass {
    6356         public Integer someMethod(Integer param) {
    6357             return param;
    6358         }
    6359     }");
    6360    
    6361     # Removed_Super_Class
    6362     writeFile($Path_v1."/RemovedSuperClass.java",
    6363     "package $PackageName;
    6364     public class RemovedSuperClass extends BaseClass {
    6365         public Integer someMethod(Integer param) {
    6366             return param;
    6367         }
    6368     }");
    6369     writeFile($Path_v2."/RemovedSuperClass.java",
    6370     "package $PackageName;
    6371     public class RemovedSuperClass {
    6372         public Integer someMethod(Integer param) {
    6373             return param;
    6374         }
    6375     }");
    6376    
    6377     # Changed_Super_Class
    6378     writeFile($Path_v1."/ChangedSuperClass.java",
    6379     "package $PackageName;
    6380     public class ChangedSuperClass extends BaseClass {
    6381         public Integer someMethod(Integer param) {
    6382             return param;
    6383         }
    6384     }");
    6385     writeFile($Path_v2."/ChangedSuperClass.java",
    6386     "package $PackageName;
    6387     public class ChangedSuperClass extends BaseClass2 {
    6388         public Integer someMethod(Integer param) {
    6389             return param;
    6390         }
    6391     }");
    6392    
    6393     # Abstract_Class_Added_Super_Interface
    6394     writeFile($Path_v1."/AbstractClassAddedSuperInterface.java",
    6395     "package $PackageName;
    6396     public abstract class AbstractClassAddedSuperInterface implements BaseInterface {
    6397         public Integer method(Integer param) {
    6398             return param;
    6399         }
    6400     }");
    6401     writeFile($Path_v2."/AbstractClassAddedSuperInterface.java",
    6402     "package $PackageName;
    6403     public abstract class AbstractClassAddedSuperInterface implements BaseInterface, BaseInterface2 {
    6404         public Integer method(Integer param) {
    6405             return param;
    6406         }
    6407     }");
    6408    
    6409     # Abstract_Class_Added_Super_Interface_With_Implemented_Methods
    6410     writeFile($Path_v1."/AbstractClassAddedSuperInterfaceWithImplementedMethods.java",
    6411     "package $PackageName;
    6412     public abstract class AbstractClassAddedSuperInterfaceWithImplementedMethods implements BaseInterface {
    6413         public Integer method(Integer param) {
    6414             return param;
    6415         }
    6416         public Integer method2(Integer param) {
    6417             return param;
    6418         }
    6419     }");
    6420     writeFile($Path_v2."/AbstractClassAddedSuperInterfaceWithImplementedMethods.java",
    6421     "package $PackageName;
    6422     public abstract class AbstractClassAddedSuperInterfaceWithImplementedMethods implements BaseInterface, BaseInterface2 {
    6423         public Integer method(Integer param) {
    6424             return param;
    6425         }
    6426         public Integer method2(Integer param) {
    6427             return param;
    6428         }
    6429     }");
    6430    
    6431     # Class_Removed_Super_Interface
    6432     writeFile($Path_v1."/ClassRemovedSuperInterface.java",
    6433     "package $PackageName;
    6434     public class ClassRemovedSuperInterface implements BaseInterface, BaseInterface2 {
    6435         public Integer method(Integer param) {
    6436             return param;
    6437         }
    6438         public Integer method2(Integer param) {
    6439             return param;
    6440         }
    6441     }");
    6442     writeFile($Path_v2."/ClassRemovedSuperInterface.java",
    6443     "package $PackageName;
    6444     public class ClassRemovedSuperInterface implements BaseInterface {
    6445         public Integer method(Integer param) {
    6446             return param;
    6447         }
    6448         public Integer method2(Integer param) {
    6449             return param;
    6450         }
    6451     }");
    6452    
    6453     writeFile($TestsPath."/Test_ClassRemovedSuperInterface.java",
    6454     "import $PackageName.*;
    6455     public class Test_ClassRemovedSuperInterface
    6456     {
    6457         public static void main(String[] args)
    6458         {
    6459             ClassRemovedSuperInterface Obj = new ClassRemovedSuperInterface();
    6460             Integer Res = Obj.method2(0);
    6461         }
    6462     }");
    6463    
    6464     # Interface_Added_Super_Interface
    6465     writeFile($Path_v1."/InterfaceAddedSuperInterface.java",
    6466     "package $PackageName;
    6467     public interface InterfaceAddedSuperInterface extends BaseInterface {
    6468         public Integer someMethod(Integer param);
    6469     }");
    6470     writeFile($Path_v2."/InterfaceAddedSuperInterface.java",
    6471     "package $PackageName;
    6472     public interface InterfaceAddedSuperInterface extends BaseInterface, BaseInterface2 {
    6473         public Integer someMethod(Integer param);
    6474     }");
    6475    
    6476     # Interface_Added_Super_Constant_Interface
    6477     writeFile($Path_v1."/InterfaceAddedSuperConstantInterface.java",
    6478     "package $PackageName;
    6479     public interface InterfaceAddedSuperConstantInterface extends BaseInterface {
    6480         public Integer someMethod(Integer param);
    6481     }");
    6482     writeFile($Path_v2."/InterfaceAddedSuperConstantInterface.java",
    6483     "package $PackageName;
    6484     public interface InterfaceAddedSuperConstantInterface extends BaseInterface, BaseConstantInterface {
    6485         public Integer someMethod(Integer param);
    6486     }");
    6487    
    6488     # Interface_Removed_Super_Interface
    6489     writeFile($Path_v1."/InterfaceRemovedSuperInterface.java",
    6490     "package $PackageName;
    6491     public interface InterfaceRemovedSuperInterface extends BaseInterface, BaseInterface2 {
    6492         public Integer someMethod(Integer param);
    6493     }");
    6494     writeFile($Path_v2."/InterfaceRemovedSuperInterface.java",
    6495     "package $PackageName;
    6496     public interface InterfaceRemovedSuperInterface extends BaseInterface {
    6497         public Integer someMethod(Integer param);
    6498     }");
    6499    
    6500     # Interface_Removed_Super_Constant_Interface
    6501     writeFile($Path_v1."/InterfaceRemovedSuperConstantInterface.java",
    6502     "package $PackageName;
    6503     public interface InterfaceRemovedSuperConstantInterface extends BaseInterface, BaseConstantInterface {
    6504         public Integer someMethod(Integer param);
    6505     }");
    6506     writeFile($Path_v2."/InterfaceRemovedSuperConstantInterface.java",
    6507     "package $PackageName;
    6508     public interface InterfaceRemovedSuperConstantInterface extends BaseInterface {
    6509         public Integer someMethod(Integer param);
    6510     }");
    6511    
    6512     # Interface_Became_Class
    6513     writeFile($Path_v1."/InterfaceBecameClass.java",
    6514     "package $PackageName;
    6515     public interface InterfaceBecameClass extends BaseInterface, BaseInterface2 {
    6516         public Integer someMethod(Integer param);
    6517     }");
    6518     writeFile($Path_v2."/InterfaceBecameClass.java",
    6519     "package $PackageName;
    6520     public class InterfaceBecameClass extends BaseClass {
    6521         public Integer someMethod(Integer param) {
    6522             return param;
    6523         }
    6524     }");
    6525    
    6526     # Removed_Class
    6527     writeFile($Path_v1."/RemovedClass.java",
    6528     "package $PackageName;
    6529     public class RemovedClass extends BaseClass {
    6530         public Integer someMethod(Integer param){
    6531             return param;
    6532         }
    6533     }");
    6534    
    6535     # Removed_Class (w/o methods)
    6536     writeFile($Path_v1."/RemovedFieldClass.java",
    6537     "package $PackageName;
    6538     public class RemovedFieldClass {
    6539         public Integer field;
    6540     }");
    6541    
    6542     writeFile($TestsPath."/Test_RemovedFieldClass.java",
    6543     "import $PackageName.*;
    6544     public class Test_RemovedFieldClass extends RemovedFieldClass
    6545     {
    6546         public static void main(String[] args)
    6547         {
    6548             RemovedFieldClass X = new RemovedFieldClass();
    6549             Integer Copy = X.field;
    6550         }
    6551     }");
    6552    
    6553     # Removed_Class (with static fields, private constructor)
    6554     writeFile($Path_v1."/RemovedClassWithStaticField.java",
    6555     "package $PackageName;
    6556     public class RemovedClassWithStaticField
    6557     {
    6558         private RemovedClassWithStaticField(){}
    6559         public static Integer cnt = 0;
    6560     }");
    6561    
    6562     writeFile($TestsPath."/Test_RemovedClassWithStaticField.java",
    6563     "import $PackageName.*;
    6564     public class Test_RemovedClassWithStaticField
    6565     {
    6566         public static void main(String[] args)
    6567         {
    6568             Integer Copy = RemovedClassWithStaticField.cnt;
    6569         }
    6570     }");
    6571    
    6572     # Removed_Field (static field, private constructor)
    6573     writeFile($Path_v1."/RemovedStaticFieldFromClassWithPrivateCtor.java",
    6574     "package $PackageName;
    6575     public class RemovedStaticFieldFromClassWithPrivateCtor
    6576     {
    6577         private RemovedStaticFieldFromClassWithPrivateCtor(){}
    6578         public static Integer cnt = 0;
    6579     }");
    6580    
    6581     writeFile($Path_v2."/RemovedStaticFieldFromClassWithPrivateCtor.java",
    6582     "package $PackageName;
    6583     public class RemovedStaticFieldFromClassWithPrivateCtor
    6584     {
    6585         private RemovedStaticFieldFromClassWithPrivateCtor(){}
    6586     }");
    6587    
    6588     writeFile($TestsPath."/Test_RemovedStaticFieldFromClassWithPrivateCtor.java",
    6589     "import $PackageName.*;
    6590     public class Test_RemovedStaticFieldFromClassWithPrivateCtor
    6591     {
    6592         public static void main(String[] args)
    6593         {
    6594             Integer Copy = RemovedStaticFieldFromClassWithPrivateCtor.cnt;
    6595         }
    6596     }");
    6597    
    6598     # Removed_Constant_Field
    6599     writeFile($Path_v1."/ClassRemovedStaticConstantField.java",
    6600     "package $PackageName;
    6601     public class ClassRemovedStaticConstantField
    6602     {
    6603         public static int removedField_Int = 1000;
    6604         public static String removedField_Str = \"Value\";
    6605     }");
    6606     writeFile($Path_v2."/ClassRemovedStaticConstantField.java",
    6607     "package $PackageName;
    6608     public class ClassRemovedStaticConstantField {
    6609     }");
    6610    
    6611     writeFile($TestsPath."/Test_ClassRemovedStaticConstantField.java",
    6612     "import $PackageName.*;
    6613     public class Test_ClassRemovedStaticConstantField
    6614     {
    6615         public static void main(String[] args)
    6616         {
    6617             Integer Copy = ClassRemovedStaticConstantField.removedField_Int;
    6618         }
    6619     }");
    6620    
    6621     # Removed_Class (Deprecated)
    6622     writeFile($Path_v1."/RemovedDeprecatedClass.java",
    6623     "package $PackageName;
    6624     \@Deprecated
    6625     public class RemovedDeprecatedClass {
    6626         public Integer someMethod(Integer param){
    6627             return param;
    6628         }
    6629     }");
    6630    
    6631     # Removed_Interface
    6632     writeFile($Path_v1."/RemovedInterface.java",
    6633     "package $PackageName;
    6634     public interface RemovedInterface extends BaseInterface, BaseInterface2 {
    6635         public Integer someMethod(Integer param);
    6636     }");
    6637    
    6638     # NonAbstract_Class_Added_Abstract_Method
    6639     writeFile($Path_v1."/NonAbstractClassAddedAbstractMethod.java",
    6640     "package $PackageName;
    6641     public class NonAbstractClassAddedAbstractMethod {
    6642         public Integer someMethod(Integer param1, String[] param2) {
    6643             return param1;
    6644         };
    6645     }");
    6646     writeFile($Path_v2."/NonAbstractClassAddedAbstractMethod.java",
    6647     "package $PackageName;
    6648     public abstract class NonAbstractClassAddedAbstractMethod {
    6649         public Integer someMethod(Integer param1, String[] param2) {
    6650             return param1;
    6651         };
    6652         public abstract Integer addedMethod(Integer param);
    6653     }");
    6654    
    6655     # Abstract_Class_Added_Abstract_Method
    6656     writeFile($Path_v1."/AbstractClassAddedAbstractMethod.java",
    6657     "package $PackageName;
    6658     public abstract class AbstractClassAddedAbstractMethod {
    6659         public Integer someMethod(Integer param1, String[] param2) {
    6660             return param1;
    6661         };
    6662     }");
    6663     writeFile($Path_v2."/AbstractClassAddedAbstractMethod.java",
    6664     "package $PackageName;
    6665     public abstract class AbstractClassAddedAbstractMethod {
    6666         public Integer someMethod(Integer param1, String[] param2) {
    6667             return param1;
    6668         };
    6669         public abstract Integer addedMethod(Integer param);
    6670     }");
    6671    
    6672     # Class_Became_Abstract
    6673     writeFile($Path_v1."/ClassBecameAbstract.java",
    6674     "package $PackageName;
    6675     public class ClassBecameAbstract {
    6676         public Integer someMethod(Integer param1, String[] param2) {
    6677             return param1;
    6678         };
    6679     }");
    6680     writeFile($Path_v2."/ClassBecameAbstract.java",
    6681     "package $PackageName;
    6682     public abstract class ClassBecameAbstract {
    6683         public Integer someMethod(Integer param1, String[] param2) {
    6684             return param1;
    6685         };
    6686         public abstract Integer addedMethod(Integer param);
    6687     }");
    6688    
    6689     # Class_Became_Final
    6690     writeFile($Path_v1."/ClassBecameFinal.java",
    6691     "package $PackageName;
    6692     public class ClassBecameFinal {
    6693         public Integer someMethod(Integer param1, String[] param2) {
    6694             return param1;
    6695         };
    6696     }");
    6697     writeFile($Path_v2."/ClassBecameFinal.java",
    6698     "package $PackageName;
    6699     public final class ClassBecameFinal {
    6700         public Integer someMethod(Integer param1, String[] param2) {
    6701             return param1;
    6702         };
    6703     }");
    6704    
    6705     # Class_Removed_Abstract_Method
    6706     writeFile($Path_v1."/ClassRemovedAbstractMethod.java",
    6707     "package $PackageName;
    6708     public abstract class ClassRemovedAbstractMethod {
    6709         public Integer someMethod(Integer param1, String[] param2) {
    6710             return param1;
    6711         };
    6712         public abstract Integer removedMethod(Integer param);
    6713     }");
    6714     writeFile($Path_v2."/ClassRemovedAbstractMethod.java",
    6715     "package $PackageName;
    6716     public abstract class ClassRemovedAbstractMethod {
    6717         public Integer someMethod(Integer param1, String[] param2) {
    6718             return param1;
    6719         };
    6720     }");
    6721    
    6722     # Class_Method_Became_Abstract
    6723     writeFile($Path_v1."/ClassMethodBecameAbstract.java",
    6724     "package $PackageName;
    6725     public abstract class ClassMethodBecameAbstract {
    6726         public Integer someMethod(Integer param1, String[] param2) {
    6727             return param1;
    6728         };
    6729         public Integer someMethod(Integer param){
    6730             return param;
    6731         };
    6732     }");
    6733     writeFile($Path_v2."/ClassMethodBecameAbstract.java",
    6734     "package $PackageName;
    6735     public abstract class ClassMethodBecameAbstract {
    6736         public Integer someMethod(Integer param1, String[] param2) {
    6737             return param1;
    6738         };
    6739         public abstract Integer someMethod(Integer param);
    6740     }");
    6741    
    6742     # Class_Method_Became_NonAbstract
    6743     writeFile($Path_v1."/ClassMethodBecameNonAbstract.java",
    6744     "package $PackageName;
    6745     public abstract class ClassMethodBecameNonAbstract {
    6746         public Integer someMethod(Integer param1, String[] param2) {
    6747             return param1;
    6748         };
    6749         public abstract Integer someMethod(Integer param);
    6750     }");
    6751     writeFile($Path_v2."/ClassMethodBecameNonAbstract.java",
    6752     "package $PackageName;
    6753     public abstract class ClassMethodBecameNonAbstract {
    6754         public Integer someMethod(Integer param1, String[] param2) {
    6755             return param1;
    6756         };
    6757         public Integer someMethod(Integer param){
    6758             return param;
    6759         };
    6760     }");
    6761    
    6762     # Method_Became_Static
    6763     writeFile($Path_v1."/MethodBecameStatic.java",
    6764     "package $PackageName;
    6765     public class MethodBecameStatic {
    6766         public Integer someMethod(Integer param) {
    6767             return param;
    6768         };
    6769     }");
    6770     writeFile($Path_v2."/MethodBecameStatic.java",
    6771     "package $PackageName;
    6772     public class MethodBecameStatic {
    6773         public static Integer someMethod(Integer param) {
    6774             return param;
    6775         };
    6776     }");
    6777    
    6778     # Method_Became_NonStatic
    6779     writeFile($Path_v1."/MethodBecameNonStatic.java",
    6780     "package $PackageName;
    6781     public class MethodBecameNonStatic {
    6782         public static Integer someMethod(Integer param) {
    6783             return param;
    6784         };
    6785     }");
    6786     writeFile($Path_v2."/MethodBecameNonStatic.java",
    6787     "package $PackageName;
    6788     public class MethodBecameNonStatic {
    6789         public Integer someMethod(Integer param) {
    6790             return param;
    6791         };
    6792     }");
    6793    
    6794     # Static_Method_Became_Final
    6795     writeFile($Path_v1."/StaticMethodBecameFinal.java",
    6796     "package $PackageName;
    6797     public class StaticMethodBecameFinal {
    6798         public static Integer someMethod(Integer param) {
    6799             return param;
    6800         };
    6801     }");
    6802     writeFile($Path_v2."/StaticMethodBecameFinal.java",
    6803     "package $PackageName;
    6804     public class StaticMethodBecameFinal {
    6805         public static final Integer someMethod(Integer param) {
    6806             return param;
    6807         };
    6808     }");
    6809    
    6810     # NonStatic_Method_Became_Final
    6811     writeFile($Path_v1."/NonStaticMethodBecameFinal.java",
    6812     "package $PackageName;
    6813     public class NonStaticMethodBecameFinal {
    6814         public Integer someMethod(Integer param) {
    6815             return param;
    6816         };
    6817     }");
    6818     writeFile($Path_v2."/NonStaticMethodBecameFinal.java",
    6819     "package $PackageName;
    6820     public class NonStaticMethodBecameFinal {
    6821         public final Integer someMethod(Integer param) {
    6822             return param;
    6823         };
    6824     }");
    6825    
    6826     # Method_Became_Abstract
    6827     writeFile($Path_v1."/MethodBecameAbstract.java",
    6828     "package $PackageName;
    6829     public abstract class MethodBecameAbstract {
    6830         public Integer someMethod(Integer param) {
    6831             return param;
    6832         };
    6833     }");
    6834     writeFile($Path_v2."/MethodBecameAbstract.java",
    6835     "package $PackageName;
    6836     public abstract class MethodBecameAbstract {
    6837         public abstract Integer someMethod(Integer param);
    6838     }");
    6839    
    6840     # Method_Became_NonAbstract
    6841     writeFile($Path_v1."/MethodBecameNonAbstract.java",
    6842     "package $PackageName;
    6843     public abstract class MethodBecameNonAbstract {
    6844         public abstract Integer someMethod(Integer param);
    6845     }");
    6846     writeFile($Path_v2."/MethodBecameNonAbstract.java",
    6847     "package $PackageName;
    6848     public abstract class MethodBecameNonAbstract {
    6849         public Integer someMethod(Integer param) {
    6850             return param;
    6851         };
    6852     }");
    6853    
    6854     # Changed_Method_Access
    6855     writeFile($Path_v1."/ChangedMethodAccess.java",
    6856     "package $PackageName;
    6857     public class ChangedMethodAccess {
    6858         public Integer someMethod(Integer param) {
    6859             return param;
    6860         };
    6861     }");
    6862     writeFile($Path_v2."/ChangedMethodAccess.java",
    6863     "package $PackageName;
    6864     public class ChangedMethodAccess {
    6865         protected Integer someMethod(Integer param) {
    6866             return param;
    6867         };
    6868     }");
    6869    
    6870     # Method_Became_Synchronized
    6871     writeFile($Path_v1."/MethodBecameSynchronized.java",
    6872     "package $PackageName;
    6873     public class MethodBecameSynchronized {
    6874         public Integer someMethod(Integer param) {
    6875             return param;
    6876         };
    6877     }");
    6878     writeFile($Path_v2."/MethodBecameSynchronized.java",
    6879     "package $PackageName;
    6880     public class MethodBecameSynchronized {
    6881         public synchronized Integer someMethod(Integer param) {
    6882             return param;
    6883         };
    6884     }");
    6885    
    6886     # Method_Became_NonSynchronized
    6887     writeFile($Path_v1."/MethodBecameNonSynchronized.java",
    6888     "package $PackageName;
    6889     public class MethodBecameNonSynchronized {
    6890         public synchronized Integer someMethod(Integer param) {
    6891             return param;
    6892         };
    6893     }");
    6894     writeFile($Path_v2."/MethodBecameNonSynchronized.java",
    6895     "package $PackageName;
    6896     public class MethodBecameNonSynchronized {
    6897         public Integer someMethod(Integer param) {
    6898             return param;
    6899         };
    6900     }");
    6901    
    6902     # Class_Overridden_Method
    6903     writeFile($Path_v1."/OverriddenMethod.java",
    6904     "package $PackageName;
    6905     public class OverriddenMethod extends BaseClass {
    6906         public Integer someMethod(Integer param) { return param; }
    6907     }");
    6908     writeFile($Path_v2."/OverriddenMethod.java",
    6909     "package $PackageName;
    6910     public class OverriddenMethod extends BaseClass {
    6911         public Integer someMethod(Integer param) { return param; }
    6912         public Integer method(Integer param) { return 2*param; }
    6913     }");
    6914    
    6915     # Class_Method_Moved_Up_Hierarchy
    6916     writeFile($Path_v1."/ClassMethodMovedUpHierarchy.java",
    6917     "package $PackageName;
    6918     public class ClassMethodMovedUpHierarchy extends BaseClass {
    6919         public Integer someMethod(Integer param) { return param; }
    6920         public Integer method(Integer param) { return 2*param; }
    6921     }");
    6922     writeFile($Path_v2."/ClassMethodMovedUpHierarchy.java",
    6923     "package $PackageName;
    6924     public class ClassMethodMovedUpHierarchy extends BaseClass {
    6925         public Integer someMethod(Integer param) { return param; }
    6926     }");
    6927    
    6928     # Class_Method_Moved_Up_Hierarchy (Interface Method) - should not be reported
    6929     writeFile($Path_v1."/InterfaceMethodMovedUpHierarchy.java",
    6930     "package $PackageName;
    6931     public interface InterfaceMethodMovedUpHierarchy extends BaseInterface {
    6932         public Integer method(Integer param);
    6933         public Integer method2(Integer param);
    6934     }");
    6935     writeFile($Path_v2."/InterfaceMethodMovedUpHierarchy.java",
    6936     "package $PackageName;
    6937     public interface InterfaceMethodMovedUpHierarchy extends BaseInterface {
    6938         public Integer method2(Integer param);
    6939     }");
    6940    
    6941     # Class_Method_Moved_Up_Hierarchy (Abstract Method) - should not be reported
    6942     writeFile($Path_v1."/AbstractMethodMovedUpHierarchy.java",
    6943     "package $PackageName;
    6944     public abstract class AbstractMethodMovedUpHierarchy implements BaseInterface {
    6945         public abstract Integer method(Integer param);
    6946         public abstract Integer method2(Integer param);
    6947     }");
    6948     writeFile($Path_v2."/AbstractMethodMovedUpHierarchy.java",
    6949     "package $PackageName;
    6950     public abstract class AbstractMethodMovedUpHierarchy implements BaseInterface {
    6951         public abstract Integer method2(Integer param);
    6952     }");
    6953    
    6954     # Use
    6955     writeFile($Path_v1."/Use.java",
    6956     "package $PackageName;
    6957     public class Use
    6958     {
    6959         public FieldBecameFinal field;
    6960         public void someMethod(FieldBecameFinal[] param) { };
    6961         public void someMethod(Use param) { };
    6962         public Integer someMethod(AbstractClassAddedSuperAbstractClass param) {
    6963             return 0;
    6964         }
    6965         public Integer someMethod(AbstractClassAddedAbstractMethod param) {
    6966             return 0;
    6967         }
    6968         public Integer someMethod(InterfaceAddedAbstractMethod param) {
    6969             return 0;
    6970         }
    6971         public Integer someMethod(InterfaceAddedSuperInterface param) {
    6972             return 0;
    6973         }
    6974         public Integer someMethod(AbstractClassAddedSuperInterface param) {
    6975             return 0;
    6976         }
    6977         public Integer someMethod(AbstractClassAddedSuperInterfaceWithImplementedMethods param) {
    6978             return 0;
    6979         }
    6980     }");
    6981     writeFile($Path_v2."/Use.java",
    6982     "package $PackageName;
    6983     public class Use
    6984     {
    6985         public FieldBecameFinal field;
    6986         public void someMethod(FieldBecameFinal[] param) { };
    6987         public void someMethod(Use param) { };
    6988         public Integer someMethod(AbstractClassAddedSuperAbstractClass param) {
    6989             return param.abstractMethod(100)+param.field;
    6990         }
    6991         public Integer someMethod(AbstractClassAddedAbstractMethod param) {
    6992             return param.addedMethod(100);
    6993         }
    6994         public Integer someMethod(InterfaceAddedAbstractMethod param) {
    6995             return param.addedMethod(100);
    6996         }
    6997         public Integer someMethod(InterfaceAddedSuperInterface param) {
    6998             return param.method2(100);
    6999         }
    7000         public Integer someMethod(AbstractClassAddedSuperInterface param) {
    7001             return param.method2(100);
    7002         }
    7003         public Integer someMethod(AbstractClassAddedSuperInterfaceWithImplementedMethods param) {
    7004             return param.method2(100);
    7005         }
    7006     }");
    7007    
    7008     # Added_Package
    7009     writeFile($Path_v2."/AddedPackage/AddedPackageClass.java",
    7010     "package $PackageName.AddedPackage;
    7011     public class AddedPackageClass {
    7012         public Integer field;
    7013         public void someMethod(Integer param) { };
    7014     }");
    7015    
    7016     # Removed_Package
    7017     writeFile($Path_v1."/RemovedPackage/RemovedPackageClass.java",
    7018     "package $PackageName.RemovedPackage;
    7019     public class RemovedPackageClass {
    7020         public Integer field;
    7021         public void someMethod(Integer param) { };
    7022     }");
    7023     my $BuildRoot1 = get_dirname($Path_v1);
    7024     my $BuildRoot2 = get_dirname($Path_v2);
    7025     if(compileJavaLib($LibName, $BuildRoot1, $BuildRoot2))
    7026     {
    7027         runTests($TestsPath, $PackageName, $BuildRoot1, $BuildRoot2);
    7028         runChecker($LibName, $BuildRoot1, $BuildRoot2);
    7029     }
    7030 }
    7031 
    7032 sub readArchive($$)
    7033 { # 1, 2 - library, 0 - client
    7034     my ($LibVersion, $Path) = @_;
    7035     return if(not $Path or not -e $Path);
    7036    
    7037     if($LibVersion)
    7038     {
    7039         my $ArchiveName = get_filename($Path);
    7040         $LibArchives{$LibVersion}{$ArchiveName} = 1;
    7041     }
    7042    
    7043     $Path = get_abs_path($Path);
    7044     my $JarCmd = get_CmdPath("jar");
    7045     if(not $JarCmd) {
    7046         exitStatus("Not_Found", "can't find \"jar\" command");
    7047     }
    7048     my $ExtractPath = joinPath($TMP_DIR, $ExtractCounter);
    7049     if(-d $ExtractPath) {
    7050         rmtree($ExtractPath);
    7051     }
    7052     mkpath($ExtractPath);
    7053     chdir($ExtractPath);
    7054     system($JarCmd." -xf \"$Path\"");
    7055     if($?) {
    7056         exitStatus("Error", "can't extract \'$Path\'");
    7057     }
    7058     chdir($ORIG_DIR);
    7059     my @Classes = ();
    7060     foreach my $ClassPath (cmd_find($ExtractPath,"","*\.class",""))
    7061     {
    7062         if($OSgroup ne "windows") {
    7063             $ClassPath=~s/\.class\Z//g;
    7064         }
    7065        
    7066         my $ClassName = get_filename($ClassPath);
    7067         if($ClassName=~/\$\d/) {
    7068             next;
    7069         }
    7070         $ClassPath = cut_path_prefix($ClassPath, $ExtractPath); # javap decompiler accepts relative paths only
    7071        
    7072         my $ClassDir = get_dirname($ClassPath);
    7073         if($ClassDir=~/\./)
    7074         { # jaxb-osgi.jar/1.0/org/apache
    7075             next;
    7076         }
    7077        
    7078         my $Package = get_PFormat($ClassDir);
    7079         if($LibVersion)
    7080         {
    7081             if(skipPackage($Package, $LibVersion))
    7082             { # internal packages
    7083                 next;
    7084             }
    7085         }
    7086        
    7087         $ClassName=~s/\$/./g; # real name for GlyphView$GlyphPainter is GlyphView.GlyphPainter
    7088         push(@Classes, $ClassPath);
    7089     }
    7090    
    7091     if($#Classes!=-1)
    7092     {
    7093         foreach my $PartRef (divideArray(\@Classes))
    7094         {
    7095             if($LibVersion) {
    7096                 readClasses($PartRef, $LibVersion, get_filename($Path));
    7097             }
    7098             else {
    7099                 readClasses_Usage($PartRef);
    7100             }
    7101         }
    7102     }
    7103    
    7104     $ExtractCounter+=1;
    7105    
    7106     if($LibVersion)
    7107     {
    7108         foreach my $SubArchive (cmd_find($ExtractPath,"","*\.jar",""))
    7109         { # recursive step
    7110             readArchive($LibVersion, $SubArchive);
    7111         }
    7112     }
    7113    
    7114     rmtree($ExtractPath);
    7115 }
    7116 
    7117 sub native_path($)
    7118 {
    7119     my $Path = $_[0];
    7120     if($OSgroup eq "windows") {
    7121         $Path=~s/[\/\\]+/\\/g;
    7122     }
    7123     return $Path;
    7124 }
    7125 
    7126 sub divideArray($)
    7127 {
    7128     my $ArrRef = $_[0];
    7129     return () if(not $ArrRef);
    7130     my @Array = @{$ArrRef};
    7131     return () if($#{$ArrRef}==-1);
    7132    
    7133     my @Res = ();
    7134     my $Sub = [];
    7135     my $Len = 0;
    7136    
    7137     foreach my $Pos (0 .. $#{$ArrRef})
    7138     {
    7139         my $Arg = $ArrRef->[$Pos];
    7140         my $Arg_L = length($Arg) + 1; # space
    7141         if($Len < $ARG_MAX - 250)
    7142         {
    7143             push(@{$Sub}, $Arg);
    7144             $Len += $Arg_L;
    7145         }
    7146         else
    7147         {
    7148             push(@Res, $Sub);
    7149            
    7150             $Sub = [$Arg];
    7151             $Len = $Arg_L;
    7152         }
    7153     }
    7154    
    7155     if($#{$Sub}!=-1) {
    7156         push(@Res, $Sub);
    7157     }
    7158    
    7159     return @Res;
    7160 }
    7161 
    7162 sub registerType($$)
    7163 {
    7164     my ($TName, $LibVersion) = @_;
    7165    
    7166     if(not $TName) {
    7167         return 0;
    7168     }
    7169    
    7170     $TName=~s/#/./g;
    7171     if($TName_Tid{$LibVersion}{$TName}) {
    7172         return $TName_Tid{$LibVersion}{$TName};
    7173     }
    7174    
    7175     if(not $TName_Tid{$LibVersion}{$TName})
    7176     {
    7177         my $ID = undef;
    7178         if($REPRODUCIBLE) {
    7179             $ID = getMd5($TName);
    7180         }
    7181         else {
    7182             $ID = ++$TYPE_ID;
    7183         }
    7184         $TName_Tid{$LibVersion}{$TName} = "$ID";
    7185     }
    7186    
    7187     my $Tid = $TName_Tid{$LibVersion}{$TName};
    7188     $TypeInfo{$LibVersion}{$Tid}{"Name"} = $TName;
    7189     if($TName=~/(.+)\[\]\Z/)
    7190     {
    7191         if(my $BaseTypeId = registerType($1, $LibVersion))
    7192         {
    7193             $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $BaseTypeId;
    7194             $TypeInfo{$LibVersion}{$Tid}{"Type"} = "array";
    7195         }
    7196     }
    7197    
    7198     return $Tid;
    7199 }
    7200 
    7201 sub readClasses_Usage($)
    7202 {
    7203     my $Paths = $_[0];
    7204     return () if(not $Paths);
    7205    
    7206     my $JavapCmd = get_CmdPath("javap");
    7207     if(not $JavapCmd) {
    7208         exitStatus("Not_Found", "can't find \"javap\" command");
    7209     }
    7210    
    7211     my $Input = join(" ", @{$Paths});
    7212     if($OSgroup ne "windows")
    7213     { # on unix ensure that the system does not try and interpret the $, by escaping it
    7214         $Input=~s/\$/\\\$/g;
    7215     }
    7216    
    7217     chdir($TMP_DIR."/".$ExtractCounter);
    7218     open(CONTENT, "$JavapCmd -c -private $Input 2>\"$TMP_DIR/warn\" |");
    7219     while(<CONTENT>)
    7220     {
    7221         if(/\/\/\s*(Method|InterfaceMethod)\s+(.+)\Z/)
    7222         {
    7223             my $M = $2;
    7224             $UsedMethods_Client{$M} = 1;
    7225            
    7226             if($M=~/\A(.*)+\.\w+\:\(/)
    7227             {
    7228                 my $C = $1;
    7229                 $C=~s/\//./g;
    7230                 $UsedClasses_Client{$C} = 1;
    7231             }
    7232         }
    7233         elsif(/\/\/\s*Field\s+(.+)\Z/)
    7234         {
    7235             my $FieldName = $1;
    7236             if(/\s+(putfield|getfield|getstatic|putstatic)\s+/) {
    7237                 $UsedFields_Client{$FieldName} = $1;
    7238             }
    7239         }
    7240         elsif(/ ([^\s]+) [^: ]+\(([^()]+)\)/)
    7241         {
    7242             my ($Ret, $Params) = ($1, $2);
    7243            
    7244             $Ret=~s/\[\]//g; # quals
    7245             $UsedClasses_Client{$Ret} = 1;
    7246            
    7247             foreach my $Param (split(/\s*,\s*/, $Params))
    7248             {
    7249                 $Param=~s/\[\]//g; # quals
    7250                 $UsedClasses_Client{$Param} = 1;
    7251             }
    7252         }
    7253         elsif(/ class /)
    7254         {
    7255             if(/extends ([^\s{]+)/)
    7256             {
    7257                 foreach my $Class (split(/\s*,\s*/, $1)) {
    7258                     $UsedClasses_Client{$Class} = 1;
    7259                 }
    7260             }
    7261            
    7262             if(/implements ([^\s{]+)/)
    7263             {
    7264                 foreach my $Interface (split(/\s*,\s*/, $1)) {
    7265                     $UsedClasses_Client{$Interface} = 1;
    7266                 }
    7267             }
    7268         }
    7269     }
    7270     close(CONTENT);
    7271     chdir($ORIG_DIR);
    7272 }
    7273 
    7274 sub readClasses($$$)
    7275 {
    7276     my ($Paths, $LibVersion, $ArchiveName) = @_;
    7277     return if(not $Paths or not $LibVersion or not $ArchiveName);
    7278    
    7279     my $JavapCmd = get_CmdPath("javap");
    7280     if(not $JavapCmd) {
    7281         exitStatus("Not_Found", "can't find \"javap\" command");
    7282     }
    7283    
    7284     my $Input = join(" ", @{$Paths});
    7285     if($OSgroup ne "windows")
    7286     { # on unix ensure that the system does not try and interpret the $, by escaping it
    7287         $Input=~s/\$/\\\$/g;
    7288     }
    7289    
    7290     my $Output = $TMP_DIR."/class-dump.txt";
    7291     if(-e $Output) {
    7292         unlink($Output);
    7293     }
    7294    
    7295     my $Cmd = "$JavapCmd -s -private";
    7296     if(not $Quick) {
    7297         $Cmd .= " -c -verbose";
    7298     }
    7299    
    7300     chdir($TMP_DIR."/".$ExtractCounter);
    7301     system($Cmd." ".$Input." >\"$Output\" 2>\"$TMP_DIR/warn\"");
    7302     chdir($ORIG_DIR);
    7303    
    7304     if(not -e $Output) {
    7305         exitStatus("Error", "internal error in parser, try to reduce ARG_MAX");
    7306     }
    7307     if($Debug) {
    7308         appendFile($DEBUG_PATH{$LibVersion}."/class-dump.txt", readFile($Output));
    7309     }
    7310    
    7311     # ! private info should be processed
    7312     open(CONTENT, "$TMP_DIR/class-dump.txt");
    7313     my @Content = <CONTENT>;
    7314     close(CONTENT);
    7315    
    7316     my (%TypeAttr, $CurrentMethod, $CurrentPackage, $CurrentClass) = ();
    7317     my ($InParamTable, $InExceptionTable, $InCode) = (0, 0, 0);
    7318    
    7319     my $InAnnotations = undef;
    7320     my $InAnnotations_Class = undef;
    7321     my $InAnnotations_Method = undef;
    7322     my %AnnotationName = ();
    7323     my %AnnotationNum = (); # support for Java 7
    7324    
    7325     my ($ParamPos, $FieldPos, $LineNum) = (0, 0, 0);
    7326     while($LineNum<=$#Content)
    7327     {
    7328         my $LINE = $Content[$LineNum++];
    7329         my $LINE_N = $Content[$LineNum];
    7330        
    7331         if($LINE=~/\A\s*(?:const|AnnotationDefault|Compiled|Source|Constant)/) {
    7332             next;
    7333         }
    7334        
    7335         if($LINE=~/\sof\s|\sline \d+:|\[\s*class|= \[|\$[\d\$\(:\.;]| class\$|[\.\/]\$|\._\d|\$eq/)
    7336         { # artificial methods and code
    7337             next;
    7338         }
    7339        
    7340         if($LINE=~/ (\w+\$|)\w+\$\w+[\(:]/) {
    7341             next;
    7342         }
    7343        
    7344         # $LINE=~s/ \$(\w)/ $1/g;
    7345         # $LINE_N=~s/ \$(\w)/ $1/g;
    7346        
    7347         if(not $InParamTable)
    7348         {
    7349             if($LINE=~/ \$/) {
    7350                 next;
    7351             }
    7352         }
    7353        
    7354         $LINE=~s/\$([\> ]|\Z)/$1/g;
    7355         $LINE_N=~s/\$([\> ]|\Z)/$1/g;
    7356        
    7357         if($LINE eq "\n" or $LINE eq "}\n")
    7358         {
    7359             $CurrentMethod = undef;
    7360             $InCode = 0;
    7361             $InAnnotations_Method = 0;
    7362             $InParamTable = 0;
    7363         }
    7364        
    7365         if($LINE eq "}\n") {
    7366             $InAnnotations_Class = 1;
    7367         }
    7368        
    7369         if($LINE=~/\A\s*#(\d+)/)
    7370         { # Constant pool
    7371             my $CNum = $1;
    7372             if($LINE=~/\s+([^ ]+?);/)
    7373             {
    7374                 my $AName = $1;
    7375                 $AName=~s/\AL//;
    7376                 $AName=~s/\$/./g;
    7377                 $AName=~s/\//./g;
    7378                
    7379                 $AnnotationName{$CNum} = $AName;
    7380                
    7381                 if(defined $AnnotationNum{$CNum})
    7382                 { # support for Java 7
    7383                     if($InAnnotations_Class) {
    7384                         $TypeAttr{"Annotations"}{registerType($AName, $LibVersion)} = 1;
    7385                     }
    7386                     delete($AnnotationNum{$CNum});
    7387                 }
    7388             }
    7389            
    7390             next;
    7391         }
    7392        
    7393         # Java 7: templates
    7394         if(index($LINE, "<")!=-1)
    7395         { # <T extends java.lang.Object>
    7396           # <KEYIN extends java.lang.Object ...
    7397             if($LINE=~/<[A-Z\d\?]+ /i)
    7398             {
    7399                 while($LINE=~/<([A-Z\d\?]+ .*?)>( |\Z)/i)
    7400                 {
    7401                     my $Str = $1;
    7402                     my @Prms = ();
    7403                     foreach my $P (separate_Params($Str, 0, 0))
    7404                     {
    7405                         $P=~s/\A([A-Z\d\?]+) .*\Z/$1/ig;
    7406                         push(@Prms, $P);
    7407                     }
    7408                     my $Str_N = join(", ", @Prms);
    7409                     $LINE=~s/\Q$Str\E/$Str_N/g;
    7410                 }
    7411             }
    7412         }
    7413        
    7414         $LINE=~s/\s*,\s*/,/g;
    7415         $LINE=~s/\$/#/g;
    7416        
    7417         if(index($LINE, "LocalVariableTable")!=-1) {
    7418             $InParamTable += 1;
    7419         }
    7420         elsif($LINE=~/Exception\s+table/) {
    7421             $InExceptionTable = 1;
    7422         }
    7423         elsif($LINE=~/\A\s*Code:/)
    7424         {
    7425             $InCode += 1;
    7426             $InAnnotations = undef;
    7427         }
    7428         elsif($LINE=~/\A\s*\d+:\s*(.*)\Z/)
    7429         { # read Code
    7430             if($InCode==1)
    7431             {
    7432                 if($CurrentMethod)
    7433                 {
    7434                     if(index($LINE, "invoke")!=-1)
    7435                     {
    7436                         if($LINE=~/ invoke(\w+) .* \/\/\s*(Method|InterfaceMethod)\s+(.+)\Z/)
    7437                         { # 3:   invokevirtual   #2; //Method "[Lcom/sleepycat/je/Database#DbState;".clone:()Ljava/lang/Object;
    7438                             my ($InvokeType, $InvokedName) = ($1, $3);
    7439                            
    7440                             if($InvokedName!~/\A(\w+:|java\/(lang|util|io)\/)/
    7441                             and index($InvokedName, '"<init>":')!=0)
    7442                             {
    7443                                 $InvokedName=~s/#/\$/g;
    7444                                 $MethodUsed{$LibVersion}{$InvokedName}{$CurrentMethod} = $InvokeType;
    7445                             }
    7446                         }
    7447                     }
    7448                     # elsif($LINE=~/ (getstatic|putstatic) .* \/\/\s*Field\s+(.+)\Z/)
    7449                     # {
    7450                     #     my $UsedFieldName = $2;
    7451                     #     $FieldUsed{$LibVersion}{$UsedFieldName}{$CurrentMethod} = 1;
    7452                     # }
    7453                 }
    7454             }
    7455             elsif(defined $InAnnotations)
    7456             {
    7457                 if($LINE=~/\A\s*\d+\:\s*#(\d+)/)
    7458                 {
    7459                     if(my $AName = $AnnotationName{$1})
    7460                     {
    7461                         if($InAnnotations_Class) {
    7462                             $TypeAttr{"Annotations"}{registerType($AName, $LibVersion)} = 1;
    7463                         }
    7464                         elsif($InAnnotations_Method) {
    7465                             $MethodInfo{$LibVersion}{$CurrentMethod}{"Annotations"}{registerType($AName, $LibVersion)} = 1;
    7466                         }
    7467                     }
    7468                     else
    7469                     { # suport for Java 7
    7470                         $AnnotationNum{$1} = 1;
    7471                     }
    7472                 }
    7473             }
    7474         }
    7475         elsif($CurrentMethod and $InParamTable==1 and $LINE=~/\A\s+0\s+\d+\s+\d+\s+(\#?)(\w+)/)
    7476         { # read parameter names from LocalVariableTable
    7477             my $Art = $1;
    7478             my $PName = $2;
    7479            
    7480             if(($PName ne "this" or $Art) and $PName=~/[a-z]/i)
    7481             {
    7482                 if($CurrentMethod)
    7483                 {
    7484                     if(defined $MethodInfo{$LibVersion}{$CurrentMethod}
    7485                     and defined $MethodInfo{$LibVersion}{$CurrentMethod}{"Param"}
    7486                     and defined $MethodInfo{$LibVersion}{$CurrentMethod}{"Param"}{$ParamPos}
    7487                     and defined $MethodInfo{$LibVersion}{$CurrentMethod}{"Param"}{$ParamPos}{"Type"})
    7488                     {
    7489                         $MethodInfo{$LibVersion}{$CurrentMethod}{"Param"}{$ParamPos}{"Name"} = $PName;
    7490                         $ParamPos++;
    7491                     }
    7492                 }
    7493             }
    7494         }
    7495         elsif($CurrentClass and $LINE=~/(\A|\s+)([^\s]+)\s+([^\s]+)\s*\((.*)\)\s*(throws\s*([^\s]+)|)\s*;\Z/)
    7496         { # attributes of methods and constructors
    7497             my (%MethodAttr, $ParamsLine, $Exceptions) = ();
    7498            
    7499             $InParamTable = 0; # read the first local variable table
    7500             $InCode = 0; # read the first code
    7501             $InAnnotations_Method = 1;
    7502             $InAnnotations_Class = 0;
    7503            
    7504             ($MethodAttr{"Return"}, $MethodAttr{"ShortName"}, $ParamsLine, $Exceptions) = ($2, $3, $4, $6);
    7505             $MethodAttr{"ShortName"}=~s/#/./g;
    7506            
    7507             if($Exceptions)
    7508             {
    7509                 foreach my $E (split(/,/, $Exceptions)) {
    7510                     $MethodAttr{"Exceptions"}{registerType($E, $LibVersion)} = 1;
    7511                 }
    7512             }
    7513             if($LINE=~/(\A|\s+)(public|protected|private)\s+/) {
    7514                 $MethodAttr{"Access"} = $2;
    7515             }
    7516             else {
    7517                 $MethodAttr{"Access"} = "package-private";
    7518             }
    7519             $MethodAttr{"Class"} = registerType($TypeAttr{"Name"}, $LibVersion);
    7520             if($MethodAttr{"ShortName"}=~/\A(|(.+)\.)\Q$CurrentClass\E\Z/)
    7521             {
    7522                 if($2)
    7523                 {
    7524                     $MethodAttr{"Package"} = $2;
    7525                     $CurrentPackage = $MethodAttr{"Package"};
    7526                     $MethodAttr{"ShortName"} = $CurrentClass;
    7527                 }
    7528                 $MethodAttr{"Constructor"} = 1;
    7529                 delete($MethodAttr{"Return"});
    7530             }
    7531             else
    7532             {
    7533                 $MethodAttr{"Return"} = registerType($MethodAttr{"Return"}, $LibVersion);
    7534             }
    7535            
    7536             my @Params = separate_Params($ParamsLine, 0, 1);
    7537            
    7538             $ParamPos = 0;
    7539             foreach my $ParamTName (@Params)
    7540             {
    7541                 %{$MethodAttr{"Param"}{$ParamPos}} = ("Type"=>registerType($ParamTName, $LibVersion), "Name"=>"p".($ParamPos+1));
    7542                 $ParamPos++;
    7543             }
    7544             $ParamPos = 0;
    7545             if(not $MethodAttr{"Constructor"})
    7546             { # methods
    7547                 if($CurrentPackage) {
    7548                     $MethodAttr{"Package"} = $CurrentPackage;
    7549                 }
    7550                 if($LINE=~/(\A|\s+)abstract\s+/) {
    7551                     $MethodAttr{"Abstract"} = 1;
    7552                 }
    7553                 if($LINE=~/(\A|\s+)final\s+/) {
    7554                     $MethodAttr{"Final"} = 1;
    7555                 }
    7556                 if($LINE=~/(\A|\s+)static\s+/) {
    7557                     $MethodAttr{"Static"} = 1;
    7558                 }
    7559                 if($LINE=~/(\A|\s+)native\s+/) {
    7560                     $MethodAttr{"Native"} = 1;
    7561                 }
    7562                 if($LINE=~/(\A|\s+)synchronized\s+/) {
    7563                     $MethodAttr{"Synchronized"} = 1;
    7564                 }
    7565             }
    7566            
    7567             # read the Signature
    7568             if($LINE_N=~/(Signature|descriptor):\s*(.+)\Z/i)
    7569             { # create run-time unique name ( java/io/PrintStream.println (Ljava/lang/String;)V )
    7570                 if($MethodAttr{"Constructor"}) {
    7571                     $CurrentMethod = $CurrentClass.".\"<init>\":".$2;
    7572                 }
    7573                 else {
    7574                     $CurrentMethod = $CurrentClass.".".$MethodAttr{"ShortName"}.":".$2;
    7575                 }
    7576                 if(my $PackageName = get_SFormat($CurrentPackage)) {
    7577                     $CurrentMethod = $PackageName."/".$CurrentMethod;
    7578                 }
    7579                
    7580                 $LineNum++;
    7581             }
    7582             else {
    7583                 exitStatus("Error", "internal error - can't read method signature");
    7584             }
    7585            
    7586             $MethodAttr{"Archive"} = $ArchiveName;
    7587             if($CurrentMethod)
    7588             {
    7589                 %{$MethodInfo{$LibVersion}{$CurrentMethod}} = %MethodAttr;
    7590                 if($MethodAttr{"Access"}=~/public|protected/)
    7591                 {
    7592                     $Class_Methods{$LibVersion}{$TypeAttr{"Name"}}{$CurrentMethod} = 1;
    7593                     if($MethodAttr{"Abstract"}) {
    7594                         $Class_AbstractMethods{$LibVersion}{$TypeAttr{"Name"}}{$CurrentMethod} = 1;
    7595                     }
    7596                 }
    7597             }
    7598         }
    7599         elsif($CurrentClass and $LINE=~/(\A|\s+)([^\s]+)\s+(\w+);\Z/)
    7600         { # fields
    7601             my ($TName, $FName) = ($2, $3);
    7602             $TypeAttr{"Fields"}{$FName}{"Type"} = registerType($TName, $LibVersion);
    7603             if($LINE=~/(\A|\s+)final\s+/) {
    7604                 $TypeAttr{"Fields"}{$FName}{"Final"} = 1;
    7605             }
    7606             if($LINE=~/(\A|\s+)static\s+/) {
    7607                 $TypeAttr{"Fields"}{$FName}{"Static"} = 1;
    7608             }
    7609             if($LINE=~/(\A|\s+)transient\s+/) {
    7610                 $TypeAttr{"Fields"}{$FName}{"Transient"} = 1;
    7611             }
    7612             if($LINE=~/(\A|\s+)volatile\s+/) {
    7613                 $TypeAttr{"Fields"}{$FName}{"Volatile"} = 1;
    7614             }
    7615             if($LINE=~/(\A|\s+)(public|protected|private)\s+/) {
    7616                 $TypeAttr{"Fields"}{$FName}{"Access"} = $2;
    7617             }
    7618             else {
    7619                 $TypeAttr{"Fields"}{$FName}{"Access"} = "package-private";
    7620             }
    7621             if($TypeAttr{"Fields"}{$FName}{"Access"}!~/private/) {
    7622                 $Class_Fields{$LibVersion}{$TypeAttr{"Name"}}{$FName}=$TypeAttr{"Fields"}{$FName}{"Type"};
    7623             }
    7624             $TypeAttr{"Fields"}{$FName}{"Pos"} = $FieldPos++;
    7625            
    7626             # read the Signature
    7627             if($Content[$LineNum++]=~/(Signature|descriptor):\s*(.+)\Z/i)
    7628             {
    7629                 my $FSignature = $2;
    7630                 if(my $PackageName = get_SFormat($CurrentPackage)) {
    7631                     $TypeAttr{"Fields"}{$FName}{"Mangled"} = $PackageName."/".$CurrentClass.".".$FName.":".$FSignature;
    7632                 }
    7633             }
    7634             if($Content[$LineNum]=~/flags:/i)
    7635             { # flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ANNOTATION
    7636                 $LineNum++;
    7637             }
    7638            
    7639             # read the Value
    7640             if($Content[$LineNum]=~/Constant\s*value:\s*([^\s]+)\s(.*)\Z/i)
    7641             {
    7642               # Java 6: Constant value: ...
    7643               # Java 7: ConstantValue: ...
    7644                 $LineNum+=1;
    7645                 my ($TName, $Value) = ($1, $2);
    7646                 if($Value)
    7647                 {
    7648                     if($Value=~s/Deprecated:\s*true\Z//g) {
    7649                         # deprecated values: ?
    7650                     }
    7651                     $TypeAttr{"Fields"}{$FName}{"Value"} = $Value;
    7652                 }
    7653                 elsif($TName eq "String") {
    7654                     $TypeAttr{"Fields"}{$FName}{"Value"} = "\@EMPTY_STRING\@";
    7655                 }
    7656             }
    7657         }
    7658         elsif($LINE=~/(\A|\s+)(class|interface)\s+([^\s\{]+)(\s+|\{|\Z)/)
    7659         { # properties of classes and interfaces
    7660             if($TypeAttr{"Name"})
    7661             { # register previous
    7662                 %{$TypeInfo{$LibVersion}{registerType($TypeAttr{"Name"}, $LibVersion)}} = %TypeAttr;
    7663             }
    7664            
    7665             %TypeAttr = ("Type"=>$2, "Name"=>$3); # reset previous class
    7666             %AnnotationName = (); # reset annotations of the class
    7667             %AnnotationNum = (); # support for Java 7
    7668             $InAnnotations_Class = 1;
    7669            
    7670             $FieldPos = 0; # reset field position
    7671             $CurrentMethod = ""; # reset current method
    7672             $TypeAttr{"Archive"} = $ArchiveName;
    7673             if($TypeAttr{"Name"}=~/\A(.+)\.([^.]+)\Z/)
    7674             {
    7675                 $CurrentClass = $2;
    7676                 $TypeAttr{"Package"} = $1;
    7677                 $CurrentPackage = $TypeAttr{"Package"};
    7678             }
    7679             else
    7680             {
    7681                 $CurrentClass = $TypeAttr{"Name"};
    7682                 $CurrentPackage = "";
    7683             }
    7684             if($CurrentClass=~s/#/./g)
    7685             { # javax.swing.text.GlyphView.GlyphPainter <=> GlyphView$GlyphPainter
    7686                 $TypeAttr{"Name"}=~s/#/./g;
    7687             }
    7688             if($LINE=~/(\A|\s+)(public|protected|private)\s+/) {
    7689                 $TypeAttr{"Access"} = $2;
    7690             }
    7691             else {
    7692                 $TypeAttr{"Access"} = "package-private";
    7693             }
    7694             if($LINE=~/\s+extends\s+([^\s\{]+)/)
    7695             {
    7696                 my $Extended = $1;
    7697                
    7698                 if($TypeAttr{"Type"} eq "class")
    7699                 {
    7700                     if($Extended ne $CurrentPackage.".".$CurrentClass) {
    7701                         $TypeAttr{"SuperClass"} = registerType($Extended, $LibVersion);
    7702                     }
    7703                 }
    7704                 elsif($TypeAttr{"Type"} eq "interface")
    7705                 {
    7706                     my @Elems = separate_Params($Extended, 0, 0);
    7707                     foreach my $SuperInterface (@Elems)
    7708                     {
    7709                         if($SuperInterface ne $CurrentPackage.".".$CurrentClass) {
    7710                             $TypeAttr{"SuperInterface"}{registerType($SuperInterface, $LibVersion)} = 1;
    7711                         }
    7712                        
    7713                         if($SuperInterface eq "java.lang.annotation.Annotation") {
    7714                             $TypeAttr{"Annotation"} = 1;
    7715                         }
    7716                     }
    7717                 }
    7718             }
    7719             if($LINE=~/\s+implements\s+([^\s\{]+)/)
    7720             {
    7721                 my $Implemented = $1;
    7722                 my @Elems = separate_Params($Implemented, 0, 0);
    7723                
    7724                 foreach my $SuperInterface (@Elems) {
    7725                     $TypeAttr{"SuperInterface"}{registerType($SuperInterface, $LibVersion)} = 1;
    7726                 }
    7727             }
    7728             if($LINE=~/(\A|\s+)abstract\s+/) {
    7729                 $TypeAttr{"Abstract"} = 1;
    7730             }
    7731             if($LINE=~/(\A|\s+)final\s+/) {
    7732                 $TypeAttr{"Final"} = 1;
    7733             }
    7734             if($LINE=~/(\A|\s+)static\s+/) {
    7735                 $TypeAttr{"Static"} = 1;
    7736             }
    7737         }
    7738         elsif(index($LINE, "Deprecated: true")!=-1
    7739         or index($LINE, "Deprecated: length")!=-1)
    7740         { # deprecated method or class
    7741             if($CurrentMethod) {
    7742                 $MethodInfo{$LibVersion}{$CurrentMethod}{"Deprecated"} = 1;
    7743             }
    7744             elsif($CurrentClass) {
    7745                 $TypeAttr{"Deprecated"} = 1;
    7746             }
    7747         }
    7748         elsif(index($LINE, "RuntimeInvisibleAnnotations")!=-1
    7749         or index($LINE, "RuntimeVisibleAnnotations")!=-1)
    7750         {
    7751             $InAnnotations = 1;
    7752             $InCode = 0;
    7753         }
    7754         elsif(defined $InAnnotations and index($LINE, "InnerClasses")!=-1) {
    7755             $InAnnotations = undef;
    7756         }
    7757         else
    7758         {
    7759             # unparsed
    7760         }
    7761     }
    7762     if($TypeAttr{"Name"})
    7763     { # register last
    7764         %{$TypeInfo{$LibVersion}{registerType($TypeAttr{"Name"}, $LibVersion)}} = %TypeAttr;
    7765     }
    7766 }
    7767 
    7768 sub separate_Params($$$)
    7769 {
    7770     my ($Params, $Comma, $Sp) = @_;
    7771     my @Parts = ();
    7772     my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
    7773     my $Part = 0;
    7774     foreach my $Pos (0 .. length($Params) - 1)
    7775     {
    7776         my $S = substr($Params, $Pos, 1);
    7777         if(defined $B{$S}) {
    7778             $B{$S} += 1;
    7779         }
    7780         if($S eq "," and
    7781         $B{"("}==$B{")"} and $B{"<"}==$B{">"})
    7782         {
    7783             if($Comma)
    7784             { # include comma
    7785                 $Parts[$Part] .= $S;
    7786             }
    7787             $Part += 1;
    7788         }
    7789         else {
    7790             $Parts[$Part] .= $S;
    7791         }
    7792     }
    7793     if(not $Sp)
    7794     { # remove spaces
    7795         foreach (@Parts)
    7796         {
    7797             s/\A //g;
    7798             s/ \Z//g;
    7799         }
    7800     }
    7801     return @Parts;
    7802 }
    7803 
    78043721sub registerUsage($$)
    78053722{
    7806     my ($TypeId, $LibVersion) = @_;
    7807     $Class_Constructed{$LibVersion}{$TypeId} = 1;
    7808     if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}) {
    7809         $Class_Constructed{$LibVersion}{$BaseId} = 1;
     3723    my ($TypeId, $LVer) = @_;
     3724    $Class_Constructed{$LVer}{$TypeId} = 1;
     3725    if(my $BaseId = $TypeInfo{$LVer}{$TypeId}{"BaseType"}) {
     3726        $Class_Constructed{$LVer}{$BaseId} = 1;
    78103727    }
    78113728}
     
    78143731{
    78153732    my $Method = $_[0];
    7816     return "" if(not $Method);
     3733   
    78173734    if($Method=~s/\)(.+)\Z/\)V/g) {
    78183735        return $Method;
    78193736    }
    7820     else {
    7821         return "";
    7822     }
     3737   
     3738    return undef;
    78233739}
    78243740
     
    78343750           
    78353751            my $ClassId = $MethodInfo{2}{$Method}{"Class"};
    7836             my %Class = get_Type($ClassId, 2);
     3752            my $CName = getTypeName($ClassId, 2);
    78373753           
    7838             $CheckedTypes{$Class{"Name"}} = 1;
     3754            $CheckedTypes{$CName} = 1;
    78393755            $CheckedMethods{$Method} = 1;
    78403756           
    78413757            if(not $MethodInfo{2}{$Method}{"Constructor"}
    7842             and my $Overridden = findMethod($Method, 2, $Class{"Name"}, 2))
     3758            and my $Overridden = findMethod($Method, 2, $CName, 2))
    78433759            {
    78443760                if(defined $MethodInfo{1}{$Overridden}
    7845                 and get_TypeType($ClassId, 2) eq "class" and $TName_Tid{1}{$Class{"Name"}})
     3761                and getTypeType($ClassId, 2) eq "class" and $TName_Tid{1}{$CName})
    78463762                { # class should exist in previous version
    7847                     %{$CompatProblems{$Overridden}{"Class_Overridden_Method"}{"this.".get_SFormat($Method)}}=(
    7848                         "Type_Name"=>$Class{"Name"},
     3763                    %{$CompatProblems{$Overridden}{"Class_Overridden_Method"}{"this.".getSFormat($Method)}}=(
     3764                        "Type_Name"=>$CName,
    78493765                        "Target"=>$MethodInfo{2}{$Method}{"Signature"},
    78503766                        "Old_Value"=>$Overridden,
    7851                         "New_Value"=>$Method  );
     3767                        "New_Value"=>$Method);
    78523768                }
    78533769            }
    78543770            if($MethodInfo{2}{$Method}{"Abstract"}) {
    7855                 $AddedMethod_Abstract{$Class{"Name"}}{$Method} = 1;
     3771                $AddedMethod_Abstract{$CName}{$Method} = 1;
    78563772            }
    78573773           
     
    78603776            if(not $MethodInfo{2}{$Method}{"Constructor"})
    78613777            {
    7862                 if(get_TypeName($MethodInfo{2}{$Method}{"Return"}, 2) ne "void"
     3778                if(getTypeName($MethodInfo{2}{$Method}{"Return"}, 2) ne "void"
    78633779                and my $VoidMethod = checkVoidMethod($Method))
    78643780                {
     
    78693785                       
    78703786                        %{$CompatProblems{$VoidMethod}{"Changed_Method_Return_From_Void"}{""}}=(
    7871                             "New_Value"=>get_TypeName($MethodInfo{2}{$Method}{"Return"}, 2)
     3787                            "New_Value"=>getTypeName($MethodInfo{2}{$Method}{"Return"}, 2)
    78723788                        );
    78733789                    }
     
    78893805           
    78903806            my $ClassId = $MethodInfo{1}{$Method}{"Class"};
    7891             my %Class = get_Type($ClassId, 1);
     3807            my $CName = getTypeName($ClassId, 1);
    78923808           
    7893             $CheckedTypes{$Class{"Name"}} = 1;
     3809            $CheckedTypes{$CName} = 1;
    78943810            $CheckedMethods{$Method} = 1;
    78953811           
    78963812            if(not $MethodInfo{1}{$Method}{"Constructor"}
    7897             and my $MovedUp = findMethod($Method, 1, $Class{"Name"}, 2))
    7898             {
    7899                 if(get_TypeType($ClassId, 1) eq "class"
    7900                 and not $MethodInfo{1}{$Method}{"Abstract"} and $TName_Tid{2}{$Class{"Name"}})
     3813            and my $MovedUp = findMethod($Method, 1, $CName, 2))
     3814            {
     3815                if(getTypeType($ClassId, 1) eq "class"
     3816                and not $MethodInfo{1}{$Method}{"Abstract"} and $TName_Tid{2}{$CName})
    79013817                {# class should exist in newer version
    7902                     %{$CompatProblems{$Method}{"Class_Method_Moved_Up_Hierarchy"}{"this.".get_SFormat($MovedUp)}}=(
    7903                         "Type_Name"=>$Class{"Name"},
     3818                    %{$CompatProblems{$Method}{"Class_Method_Moved_Up_Hierarchy"}{"this.".getSFormat($MovedUp)}}=(
     3819                        "Type_Name"=>$CName,
    79043820                        "Target"=>$MethodInfo{2}{$MovedUp}{"Signature"},
    79053821                        "Old_Value"=>$Method,
    7906                         "New_Value"=>$MovedUp  );
     3822                        "New_Value"=>$MovedUp);
    79073823                }
    79083824            }
     
    79103826            {
    79113827                if($MethodInfo{1}{$Method}{"Abstract"}) {
    7912                     $RemovedMethod_Abstract{$Class{"Name"}}{$Method} = 1;
     3828                    $RemovedMethod_Abstract{$CName}{$Method} = 1;
    79133829                }
    79143830                %{$CompatProblems{$Method}{"Removed_Method"}{""}}=();
     
    79183834}
    79193835
    7920 sub getArchives($)
    7921 {
    7922     my $LibVersion = $_[0];
    7923     my @Paths = ();
    7924     foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Archives"}))
    7925     {
    7926         if(not -e $Path) {
    7927             exitStatus("Access_Error", "can't access \'$Path\'");
    7928         }
    7929         foreach (getArchivePaths($Path, $LibVersion)) {
    7930             push(@Paths, $_);
    7931         }
    7932     }
    7933     return @Paths;
    7934 }
    7935 
    79363836sub getArchivePaths($$)
    79373837{
    7938     my ($Dest, $LibVersion) = @_;
     3838    my ($Dest, $LVer) = @_;
    79393839    if(-f $Dest) {
    79403840        return ($Dest);
     
    79433843    {
    79443844        $Dest=~s/[\/\\]+\Z//g;
    7945         my @AllClasses = ();
    7946         foreach my $Path (cmd_find($Dest,"","*\.jar",""))
    7947         {
    7948             next if(ignore_path($Path, $Dest));
    7949             push(@AllClasses, resolve_symlink($Path));
    7950         }
    7951         return @AllClasses;
     3845        next if(not $Dest);
     3846       
     3847        my @Archives = ();
     3848        foreach my $Path (cmdFind($Dest, "", "*\\.jar"))
     3849        {
     3850            next if(ignorePath($Path, $Dest));
     3851            push(@Archives, realpath_F($Path));
     3852        }
     3853        return @Archives;
    79523854    }
    79533855    return ();
    79543856}
    79553857
    7956 sub isCyclical($$)
    7957 {
     3858sub isCyclical($$) {
    79583859    return (grep {$_ eq $_[1]} @{$_[0]});
    79593860}
    79603861
    7961 sub read_symlink($)
    7962 {
    7963     my $Path = $_[0];
    7964     return "" if(not $Path or not -f $Path);
    7965     return $Cache{"read_symlink"}{$Path} if(defined $Cache{"read_symlink"}{$Path});
    7966     if(my $ReadlinkCmd = get_CmdPath("readlink"))
    7967     {
    7968         my $Res = `$ReadlinkCmd -n \"$Path\"`;
    7969         return ($Cache{"read_symlink"}{$Path} = $Res);
    7970     }
    7971     elsif(my $FileCmd = get_CmdPath("file"))
    7972     {
    7973         my $Info = `$FileCmd \"$Path\"`;
    7974         if($Info=~/symbolic\s+link\s+to\s+['`"]*([\w\d\.\-\/\\]+)['`"]*/i) {
    7975             return ($Cache{"read_symlink"}{$Path} = $1);
    7976         }
    7977     }
    7978     return ($Cache{"read_symlink"}{$Path} = "");
    7979 }
    7980 
    7981 sub resolve_symlink($)
    7982 {
    7983     my $Path = $_[0];
    7984     return "" if(not $Path or not -f $Path);
    7985     return $Path if(isCyclical(\@RecurSymlink, $Path));
    7986     push(@RecurSymlink, $Path);
    7987     if(-l $Path and my $Redirect=read_symlink($Path))
    7988     {
    7989         if(is_abs($Redirect))
    7990         {
    7991             my $Res = resolve_symlink($Redirect);
    7992             pop(@RecurSymlink);
    7993             return $Res;
    7994         }
    7995         elsif($Redirect=~/\.\.[\/\\]/)
    7996         {
    7997             $Redirect = joinPath(get_dirname($Path),$Redirect);
    7998             while($Redirect=~s&(/|\\)[^\/\\]+(\/|\\)\.\.(\/|\\)&$1&){};
    7999             my $Res = resolve_symlink($Redirect);
    8000             pop(@RecurSymlink);
    8001             return $Res;
    8002         }
    8003         elsif(-f get_dirname($Path)."/".$Redirect)
    8004         {
    8005             my $Res = resolve_symlink(joinPath(get_dirname($Path),$Redirect));
    8006             pop(@RecurSymlink);
    8007             return $Res;
    8008         }
    8009         return $Path;
     3862sub mergeAPIs($$)
     3863{
     3864    my ($LVer, $Dep) = @_;
     3865   
     3866    foreach my $TId (keys(%{$Dep->{"TypeInfo"}}))
     3867    {
     3868        $TypeInfo{$LVer}{$TId} = $Dep->{"TypeInfo"}{$TId};
     3869        $TypeInfo{$LVer}{$TId}{"Dep"} = 1;
     3870    }
     3871   
     3872    my $MInfo = $Dep->{"MethodInfo"};
     3873    foreach my $M_Id (keys(%{$MInfo}))
     3874    {
     3875        if(my $Name = $MInfo->{$M_Id}{"Name"})
     3876        {
     3877            $MethodInfo{$LVer}{$Name} = $MInfo->{$M_Id};
     3878            $MethodInfo{$LVer}{$Name}{"Dep"} = 1;
     3879        }
     3880    }
     3881}
     3882
     3883sub readAPIDump($$$)
     3884{
     3885    my ($LVer, $Path, $Subj) = @_;
     3886   
     3887    if(not $In::Opt{"CountMethods"}) {
     3888        printMsg("INFO", "Reading API dump ($LVer) ...");
     3889    }
     3890   
     3891    my $FilePath = "";
     3892    if(isDump_U($Path))
     3893    { # input *.dump
     3894        $FilePath = $Path;
    80103895    }
    80113896    else
    8012     {
    8013         pop(@RecurSymlink);
    8014         return $Path;
    8015     }
    8016 }
    8017 
    8018 sub cmpVersions($$)
    8019 {# compare two version strings in dotted-numeric format
    8020     my ($V1, $V2) = @_;
    8021     return 0 if($V1 eq $V2);
    8022     my @V1Parts = split(/\./, $V1);
    8023     my @V2Parts = split(/\./, $V2);
    8024     for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++) {
    8025         return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
    8026         return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
    8027     }
    8028     return -1 if($#V1Parts < $#V2Parts);
    8029     return 1 if($#V1Parts > $#V2Parts);
    8030     return 0;
    8031 }
    8032 
    8033 sub majorVersion($)
    8034 {
    8035     my $Version = $_[0];
    8036     return 0 if(not $Version);
    8037     my @VParts = split(/\./, $Version);
    8038     return $VParts[0];
    8039 }
    8040 
    8041 sub isDump($)
    8042 {
    8043     if($_[0]=~/\A(.+)\.(api|dump|apidump)(\Q.tar.gz\E|\Q.zip\E|)\Z/)
    8044     { # returns a name of package
    8045         return $1;
    8046     }
    8047     return 0;
    8048 }
    8049 
    8050 sub isDumpFile($)
    8051 {
    8052     if($_[0]=~/\.(api|dump|apidump)\Z/)
    8053     {
    8054         return 1;
    8055     }
    8056     return 0;
    8057 }
    8058 
    8059 sub read_API_Dump($$$)
    8060 {
    8061     my ($LibVersion, $Path, $Subj) = @_;
    8062     return if(not $LibVersion or not -e $Path);
    8063    
    8064     my $FilePath = unpackDump($Path);
    8065     if(not isDumpFile($FilePath)) {
    8066         exitStatus("Invalid_Dump", "specified API dump \'$Path\' is not valid, try to recreate it");
    8067     }
    8068     my $Content = readFile($FilePath);
    8069     rmtree($TMP_DIR."/unpack");
     3897    { # input *.dump.tar.gz
     3898        $FilePath = unpackDump($Path);
     3899        if(not isDump_U($FilePath)) {
     3900            exitStatus("Invalid_Dump", "specified API dump \'$Path\' is not valid, try to recreate it");
     3901        }
     3902    }
     3903   
     3904    my $APIRef = {};
     3905   
     3906    open(DUMP, $FilePath);
     3907    local $/ = undef;
     3908    my $Content = <DUMP>;
     3909    close(DUMP);
     3910   
     3911    if(getDirname($FilePath) eq $In::Opt{"Tmp"}."/unpack")
     3912    { # remove temp file
     3913        unlink($FilePath);
     3914    }
    80703915   
    80713916    if($Content!~/};\s*\Z/) {
    80723917        exitStatus("Invalid_Dump", "specified API dump \'$Path\' is not valid, try to recreate it");
    80733918    }
    8074     my $APIDump = eval($Content);
    8075     if(not $APIDump) {
     3919   
     3920    $APIRef = eval($Content);
     3921   
     3922    if(not $APIRef) {
    80763923        exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
    80773924    }
    8078     my $DumpVersion = $APIDump->{"API_DUMP_VERSION"};
    8079     if(majorVersion($DumpVersion) ne $API_DUMP_MAJOR)
    8080     { # compatible with the dumps of the same major version
    8081         exitStatus("Dump_Version", "incompatible version $DumpVersion of specified API dump (allowed only $API_DUMP_MAJOR.0<=V<=$API_DUMP_MAJOR.9)");
    8082     }
    8083    
    8084     if(defined $TypeInfo{$LibVersion})
    8085     {
    8086         foreach my $TId (keys(%{$APIDump->{"TypeInfo"}}))
    8087         {
    8088             $TypeInfo{$LibVersion}{$TId} = $APIDump->{"TypeInfo"}{$TId};
    8089         }
    8090     }
    8091     else {
    8092         $TypeInfo{$LibVersion} = $APIDump->{"TypeInfo"};
    8093     }
    8094    
    8095     foreach my $TypeId (keys(%{$APIDump->{"TypeInfo"}}))
    8096     {
    8097         my %TypeAttr = %{$TypeInfo{$LibVersion}{$TypeId}};
    8098         $TName_Tid{$LibVersion}{$TypeAttr{"Name"}} = $TypeId;
    8099        
    8100         if($Subj ne "Dep")
    8101         {
    8102             if(my $Archive = $TypeAttr{"Archive"}) {
    8103                 $LibArchives{$LibVersion}{$Archive} = 1;
    8104             }
    8105         }
    8106        
    8107         foreach my $FieldName (keys(%{$TypeAttr{"Fields"}}))
    8108         {
    8109             if($TypeAttr{"Fields"}{$FieldName}{"Access"}=~/public|protected/) {
    8110                 $Class_Fields{$LibVersion}{$TypeAttr{"Name"}}{$FieldName} = $TypeAttr{"Fields"}{$FieldName}{"Type"};
    8111             }
    8112         }
    8113        
    8114         if($Subj eq "Dep") {
    8115             $TypeInfo{$LibVersion}{$TypeId}{"Dep"} = 1;
    8116         }
    8117     }
    8118     my $MInfo = $APIDump->{"MethodInfo"};
    8119     foreach my $M_Id (keys(%{$MInfo}))
    8120     {
    8121         my $Name = $MInfo->{$M_Id}{"Name"};
    8122         $MethodInfo{$LibVersion}{$Name} = $MInfo->{$M_Id};
    8123        
    8124         if($Subj eq "Dep") {
    8125             $MethodInfo{$LibVersion}{$Name}{"Dep"} = 1;
    8126         }
    8127     }
    8128    
    8129     my $MUsed = $APIDump->{"MethodUsed"};
    8130     foreach my $M_Id (keys(%{$MUsed}))
    8131     {
    8132         my $Name = $MUsed->{$M_Id}{"Name"};
    8133         $MethodUsed{$LibVersion}{$Name} = $MUsed->{$M_Id}{"Used"};
    8134     }
    8135    
    8136     foreach my $Method (keys(%{$MethodInfo{$LibVersion}}))
    8137     {
    8138         if(my $ClassId = $MethodInfo{$LibVersion}{$Method}{"Class"}
    8139         and $MethodInfo{$LibVersion}{$Method}{"Access"}=~/public|protected/)
    8140         {
    8141             $Class_Methods{$LibVersion}{get_TypeName($ClassId, $LibVersion)}{$Method} = 1;
    8142             if($MethodInfo{$LibVersion}{$Method}{"Abstract"}) {
    8143                 $Class_AbstractMethods{$LibVersion}{get_TypeName($ClassId, $LibVersion)}{$Method} = 1;
    8144             }
    8145         }
    8146     }
    8147    
    8148     # $FieldUsed{$LibVersion} = $APIDump->{"FieldUsed"};
    8149    
    8150     if(keys(%{$LibArchives{$LibVersion}})) {
    8151         $Descriptor{$LibVersion}{"Archives"} = "OK";
    8152     }
    8153     $Descriptor{$LibVersion}{"Version"} = $APIDump->{"LibraryVersion"};
    8154     $Descriptor{$LibVersion}{"Dump"} = 1;
    8155 }
    8156 
    8157 sub createDescriptor($$)
    8158 {
    8159     my ($LibVersion, $Path) = @_;
    8160     return if(not $LibVersion or not $Path or not -e $Path);
    8161    
    8162     if(isDump($Path))
    8163     { # API dump
    8164         read_API_Dump($LibVersion, $Path, "Main");
    8165     }
    8166     else
    8167     {
    8168         if(-d $Path or $Path=~/\.jar\Z/)
    8169         {
    8170             readDescriptor($LibVersion,"
    8171               <version>
    8172                   ".$TargetVersion{$LibVersion}."
    8173               </version>
    8174              
    8175               <archives>
    8176                   $Path
    8177               </archives>");
    8178         }
    8179         else
    8180         { # standard XML descriptor
    8181             readDescriptor($LibVersion, readFile($Path));
    8182         }
    8183     }
    8184    
    8185     if(my $Dep = $DepDump{$LibVersion}) {
    8186         read_API_Dump($LibVersion, $Dep, "Dep");
    8187     }
    8188 }
    8189 
    8190 sub get_version($)
    8191 {
    8192     my $Cmd = $_[0];
    8193     return "" if(not $Cmd);
    8194     my $Version = `$Cmd --version 2>\"$TMP_DIR/null\"`;
    8195     return $Version;
    8196 }
    8197 
    8198 sub get_depth($)
    8199 {
    8200     if(defined $Cache{"get_depth"}{$_[0]}) {
    8201         return $Cache{"get_depth"}{$_[0]}
    8202     }
    8203     return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
    8204 }
    8205 
    8206 sub show_time_interval($)
    8207 {
    8208     my $Interval = $_[0];
    8209     my $Hr = int($Interval/3600);
    8210     my $Min = int($Interval/60)-$Hr*60;
    8211     my $Sec = $Interval-$Hr*3600-$Min*60;
    8212     if($Hr) {
    8213         return "$Hr hr, $Min min, $Sec sec";
    8214     }
    8215     elsif($Min) {
    8216         return "$Min min, $Sec sec";
    8217     }
    8218     else {
    8219         return "$Sec sec";
    8220     }
     3925   
     3926    my $APIVer = $APIRef->{"API_DUMP_VERSION"};
     3927   
     3928    if($APIVer)
     3929    {
     3930        if(cmpVersions($APIVer, $API_DUMP_VERSION)>0)
     3931        { # future formats
     3932            exitStatus("Dump_Version", "the versions of the API dump is newer than version of the tool");
     3933        }
     3934    }
     3935   
     3936    if(cmpVersions($APIVer, $API_DUMP_VERSION_MIN)<0) {
     3937        exitStatus("Dump_Version", "the version of the API dump is too old and unsupported anymore, please regenerate it");
     3938    }
     3939   
     3940    if($Subj ne "Dep")
     3941    {
     3942        $In::Desc{$LVer}{"Version"} = $APIRef->{"LibraryVersion"};
     3943        $In::Desc{$LVer}{"Dump"} = 1;
     3944    }
     3945   
     3946    return $APIRef;
    82213947}
    82223948
    82233949sub checkVersionNum($$)
    82243950{
    8225     my ($LibVersion, $Path) = @_;
    8226    
    8227     if($TargetVersion{$LibVersion}) {
     3951    my ($LVer, $Path) = @_;
     3952   
     3953    if($In::Desc{$LVer}{"TargetVersion"}) {
    82283954        return;
    82293955    }
     
    82363962   
    82373963    if(not defined $Ver) {
    8238         $Ver = getManifestVersion(get_abs_path($Path));
     3964        $Ver = getManifestVersion(getAbsPath($Path));
    82393965    }
    82403966   
    82413967    if(not defined $Ver) {
    8242         $Ver = getPkgVersion(get_filename($Path));
     3968        $Ver = getPkgVersion(getFilename($Path));
    82433969    }
    82443970   
     
    82493975    if(not defined $Ver)
    82503976    {
    8251         if($DumpAPI)
     3977        if($In::Opt{"DumpAPI"})
    82523978        {
    82533979            $Ver = "XYZ";
     
    82553981        else
    82563982        {
    8257             if($LibVersion==1) {
     3983            if($LVer==1) {
    82583984                $Ver = "X";
    82593985            }
     
    82643990    }
    82653991   
    8266     $TargetVersion{$LibVersion} = $Ver;
    8267    
    8268     if($DumpAPI) {
     3992    $In::Desc{$LVer}{"TargetVersion"} = $Ver;
     3993   
     3994    if($In::Opt{"DumpAPI"}) {
    82693995        printMsg("WARNING", "set version number to $Ver (use -vnum option to change it)");
    82703996    }
    82713997    else {
    8272         printMsg("WARNING", "set #$LibVersion version number to $Ver (use --v$LibVersion=NUM option to change it)");
     3998        printMsg("WARNING", "set #$LVer version number to $Ver (use --v$LVer=NUM option to change it)");
    82733999    }
    82744000}
     
    82784004    my $Path = $_[0];
    82794005   
    8280     if(not $Path or not -e $Path) {
    8281         return undef;
    8282     }
    8283    
    8284     my $JarCmd = get_CmdPath("jar");
     4006    my $JarCmd = getCmdPath("jar");
    82854007    if(not $JarCmd) {
    82864008        exitStatus("Not_Found", "can't find \"jar\" command");
    82874009    }
    8288     chdir($TMP_DIR);
     4010   
     4011    my $TmpDir = $In::Opt{"Tmp"};
     4012   
     4013    chdir($TmpDir);
    82894014    system($JarCmd." -xf \"$Path\" META-INF 2>null");
    8290     chdir($ORIG_DIR);
    8291     if(my $Content = readFile("$TMP_DIR/META-INF/MANIFEST.MF"))
    8292     {
    8293         if($Content=~/(\A|\s)Implementation\-Version:\s*(.+)(\s|\Z)/i) {
    8294             return $2;
     4015    chdir($In::Opt{"OrigDir"});
     4016   
     4017    my $Manifest = $TmpDir."/META-INF/MANIFEST.MF";
     4018   
     4019    if(-f $Manifest)
     4020    {
     4021        if(my $Content = readFile($Manifest))
     4022        {
     4023            if($Content=~/(\A|\s)Implementation\-Version:\s*(.+)(\s|\Z)/i) {
     4024                return $2;
     4025            }
    82954026        }
    82964027    }
     
    83374068}
    83384069
    8339 sub get_OSgroup()
    8340 {
    8341     if($Config{"osname"}=~/macos|darwin|rhapsody/i) {
    8342         return "macos";
    8343     }
    8344     elsif($Config{"osname"}=~/freebsd|openbsd|netbsd/i) {
    8345         return "bsd";
    8346     }
    8347     elsif($Config{"osname"}=~/haiku|beos/i) {
    8348         return "beos";
    8349     }
    8350     elsif($Config{"osname"}=~/symbian|epoc/i) {
    8351         return "symbian";
    8352     }
    8353     elsif($Config{"osname"}=~/win/i) {
    8354         return "windows";
    8355     }
    8356     else {
    8357         return $Config{"osname"};
    8358     }
    8359 }
    8360 
    8361 sub get_ARG_MAX()
    8362 {
    8363     if($OSgroup eq "windows") {
    8364         return 1990; # 8191, 2047
    8365     }
    8366     else
    8367     { # Linux
    8368       # TODO: set max possible value (~131000)
    8369         return 32767;
    8370     }
    8371 }
    8372 
    8373 sub dump_sorting($)
     4070sub dumpSorting($)
    83744071{
    83754072    my $Hash = $_[0];
     
    83874084}
    83884085
    8389 sub detect_bin_default_paths()
    8390 {
    8391     my $EnvPaths = $ENV{"PATH"};
    8392     if($OSgroup eq "beos") {
    8393         $EnvPaths.=":".$ENV{"BETOOLS"};
    8394     }
    8395     elsif($OSgroup eq "windows"
    8396     and my $JHome = $ENV{"JAVA_HOME"}) {
    8397         $EnvPaths.=";$JHome\\bin";
    8398     }
    8399     my $Sep = ($OSgroup eq "windows")?";":":|;";
    8400     foreach my $Path (sort {length($a)<=>length($b)} split(/$Sep/, $EnvPaths))
    8401     {
    8402         $Path=~s/[\/\\]+\Z//g;
    8403         next if(not $Path);
    8404         $DefaultBinPaths{$Path} = 1;
    8405     }
    8406 }
    8407 
    8408 sub detect_default_paths()
    8409 {
    8410     if(keys(%SystemPaths))
    8411     {# run once
    8412         return;
    8413     }
    8414    
    8415     foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
    8416     {# additional search paths
    8417         foreach my $Path (keys(%{$OS_AddPath{$OSgroup}{$Type}}))
    8418         {
    8419             next if(not -d $Path);
    8420             $SystemPaths{$Type}{$Path} = $OS_AddPath{$OSgroup}{$Type}{$Path};
    8421         }
    8422     }
    8423     if($OSgroup ne "windows")
    8424     {
    8425         foreach my $Type ("include", "lib", "bin")
    8426         {# autodetecting system "devel" directories
    8427             foreach my $Path (cmd_find("/","d","*$Type*",1)) {
    8428                 $SystemPaths{$Type}{$Path} = 1;
    8429             }
    8430             if(-d "/usr") {
    8431                 foreach my $Path (cmd_find("/usr","d","*$Type*",1)) {
    8432                     $SystemPaths{$Type}{$Path} = 1;
    8433                 }
    8434             }
    8435         }
    8436     }
    8437     detect_bin_default_paths();
    8438     foreach my $Path (keys(%DefaultBinPaths)) {
    8439         $SystemPaths{"bin"}{$Path} = $DefaultBinPaths{$Path};
    8440     }
    8441    
    8442     if(not $TestSystem)
    8443     {
    8444         if(my $JavacCmd = get_CmdPath("javac"))
    8445         {
    8446             if(my $Ver = `$JavacCmd -version 2>&1`)
    8447             {
    8448                 if($Ver=~/javac\s+(.+)/) {
    8449                     printMsg("INFO", "using Java ".$1);
    8450                 }
    8451             }
    8452         }
    8453     }
    8454 }
    8455 
    8456 sub exitStatus($$)
    8457 {
    8458     my ($Code, $Msg) = @_;
    8459     print STDERR "ERROR: ". $Msg."\n";
    8460     exit($ERROR_CODE{$Code});
    8461 }
    8462 
    8463 sub printMsg($$)
    8464 {
    8465     my ($Type, $Msg) = @_;
    8466     if($Type!~/\AINFO/) {
    8467         $Msg = $Type.": ".$Msg;
    8468     }
    8469     if($Type!~/_C\Z/) {
    8470         $Msg .= "\n";
    8471     }
    8472     if($Type eq "ERROR") {
    8473         print STDERR $Msg;
    8474     }
    8475     else {
    8476         print $Msg;
    8477     }
    8478 }
    8479 
    84804086sub printStatMsg($)
    84814087{
    84824088    my $Level = $_[0];
    8483     printMsg("INFO", "total ".lc($Level)." compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
     4089    printMsg("INFO", "Total ".lc($Level)." compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
    84844090}
    84854091
    84864092sub printReport()
    84874093{
    8488     printMsg("INFO", "creating compatibility report ...");
     4094    printMsg("INFO", "Creating compatibility report ...");
    84894095    createReport();
    8490     if($JoinReport or $DoubleReport)
     4096    if($In::Opt{"JoinReport"} or $In::Opt{"DoubleReport"})
    84914097    {
    84924098        if($RESULT{"Binary"}{"Problems"}
    84934099        or $RESULT{"Source"}{"Problems"})
    84944100        {
    8495             printMsg("INFO", "binary compatibility: ".(100-$RESULT{"Binary"}{"Affected"})."\%");
    8496             printMsg("INFO", "source compatibility: ".(100-$RESULT{"Source"}{"Affected"})."\%");
     4101            printMsg("INFO", "Binary compatibility: ".(100-$RESULT{"Binary"}{"Affected"})."\%");
     4102            printMsg("INFO", "Source compatibility: ".(100-$RESULT{"Source"}{"Affected"})."\%");
    84974103        }
    84984104        else
    84994105        {
    8500             printMsg("INFO", "binary compatibility: 100\%");
    8501             printMsg("INFO", "source compatibility: 100\%");
     4106            printMsg("INFO", "Binary compatibility: 100\%");
     4107            printMsg("INFO", "Source compatibility: 100\%");
    85024108        }
    85034109        printStatMsg("Binary");
    85044110        printStatMsg("Source");
    85054111    }
    8506     elsif($BinaryOnly)
     4112    elsif($In::Opt{"BinaryOnly"})
    85074113    {
    85084114        if($RESULT{"Binary"}{"Problems"}) {
    8509             printMsg("INFO", "binary compatibility: ".(100-$RESULT{"Binary"}{"Affected"})."\%");
     4115            printMsg("INFO", "Binary compatibility: ".(100-$RESULT{"Binary"}{"Affected"})."\%");
    85104116        }
    85114117        else {
    8512             printMsg("INFO", "binary compatibility: 100\%");
     4118            printMsg("INFO", "Binary compatibility: 100\%");
    85134119        }
    85144120        printStatMsg("Binary");
    85154121    }
    8516     elsif($SourceOnly)
     4122    elsif($In::Opt{"SourceOnly"})
    85174123    {
    85184124        if($RESULT{"Source"}{"Problems"}) {
    8519             printMsg("INFO", "source compatibility: ".(100-$RESULT{"Source"}{"Affected"})."\%");
     4125            printMsg("INFO", "Source compatibility: ".(100-$RESULT{"Source"}{"Affected"})."\%");
    85204126        }
    85214127        else {
    8522             printMsg("INFO", "source compatibility: 100\%");
     4128            printMsg("INFO", "Source compatibility: 100\%");
    85234129        }
    85244130        printStatMsg("Source");
    85254131    }
    8526     if($JoinReport)
    8527     {
    8528         printMsg("INFO", "report: ".getReportPath("Join"));
    8529     }
    8530     elsif($DoubleReport)
     4132    if($In::Opt{"JoinReport"})
     4133    {
     4134        printMsg("INFO", "Report: ".getReportPath("Join"));
     4135    }
     4136    elsif($In::Opt{"DoubleReport"})
    85314137    { # default
    8532         printMsg("INFO", "report (BC): ".getReportPath("Binary"));
    8533         printMsg("INFO", "report (SC): ".getReportPath("Source"));
    8534     }
    8535     elsif($BinaryOnly)
     4138        printMsg("INFO", "Report (BC): ".getReportPath("Binary"));
     4139        printMsg("INFO", "Report (SC): ".getReportPath("Source"));
     4140    }
     4141    elsif($In::Opt{"BinaryOnly"})
    85364142    { # --binary
    8537         printMsg("INFO", "report: ".getReportPath("Binary"));
    8538     }
    8539     elsif($SourceOnly)
     4143        printMsg("INFO", "Report: ".getReportPath("Binary"));
     4144    }
     4145    elsif($In::Opt{"SourceOnly"})
    85404146    { # --source
    8541         printMsg("INFO", "report: ".getReportPath("Source"));
     4147        printMsg("INFO", "Report: ".getReportPath("Source"));
    85424148    }
    85434149}
     
    85464152{
    85474153    my $Level = $_[0];
    8548     my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
     4154    my $Dir = "compat_reports/".$In::Opt{"TargetLib"}."/".$In::Desc{1}{"Version"}."_to_".$In::Desc{2}{"Version"};
    85494155    if($Level eq "Binary")
    85504156    {
    8551         if($BinaryReportPath)
     4157        if($In::Opt{"BinaryReportPath"})
    85524158        { # --bin-report-path
    8553             return $BinaryReportPath;
    8554         }
    8555         elsif($OutputReportPath)
     4159            return $In::Opt{"BinaryReportPath"};
     4160        }
     4161        elsif($In::Opt{"OutputReportPath"})
    85564162        { # --report-path
    8557             return $OutputReportPath;
     4163            return $In::Opt{"OutputReportPath"};
    85584164        }
    85594165        else
     
    85644170    elsif($Level eq "Source")
    85654171    {
    8566         if($SourceReportPath)
     4172        if($In::Opt{"SourceReportPath"})
    85674173        { # --src-report-path
    8568             return $SourceReportPath;
    8569         }
    8570         elsif($OutputReportPath)
     4174            return $In::Opt{"SourceReportPath"};
     4175        }
     4176        elsif($In::Opt{"OutputReportPath"})
    85714177        { # --report-path
    8572             return $OutputReportPath;
     4178            return $In::Opt{"OutputReportPath"};
    85734179        }
    85744180        else
     
    85794185    else
    85804186    {
    8581         if($OutputReportPath)
     4187        if($In::Opt{"OutputReportPath"})
    85824188        { # --report-path
    8583             return $OutputReportPath;
     4189            return $In::Opt{"OutputReportPath"};
    85844190        }
    85854191        else
     
    85904196}
    85914197
    8592 sub initLogging($)
    8593 {
    8594     my $LibVersion = $_[0];
    8595     if($Debug)
    8596     { # debug directory
    8597         $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
    8598        
    8599         if(-d $DEBUG_PATH{$LibVersion}) {
    8600             rmtree($DEBUG_PATH{$LibVersion});
     4198sub unpackDump($)
     4199{
     4200    my $Path = $_[0];
     4201   
     4202    if(isDump_U($Path)) {
     4203        return $Path;
     4204    }
     4205   
     4206    my $TmpDir = $In::Opt{"Tmp"};
     4207   
     4208    $Path = getAbsPath($Path);
     4209    $Path = pathFmt($Path);
     4210   
     4211    my ($Dir, $FileName) = sepPath($Path);
     4212    my $UnpackDir = $TmpDir."/unpack";
     4213    if(-d $UnpackDir) {
     4214        rmtree($UnpackDir);
     4215    }
     4216    mkpath($UnpackDir);
     4217   
     4218    if($FileName=~s/\Q.zip\E\Z//g)
     4219    { # *.zip
     4220        my $UnzipCmd = getCmdPath("unzip");
     4221        if(not $UnzipCmd) {
     4222            exitStatus("Not_Found", "can't find \"unzip\" command");
     4223        }
     4224        chdir($UnpackDir);
     4225        system("$UnzipCmd \"$Path\" >contents.txt");
     4226        if($?) {
     4227            exitStatus("Error", "can't extract \'$Path\'");
     4228        }
     4229        chdir($In::Opt{"OrigDir"});
     4230        my @Contents = ();
     4231        foreach (split("\n", readFile("$UnpackDir/contents.txt")))
     4232        {
     4233            if(/inflating:\s*([^\s]+)/) {
     4234                push(@Contents, $1);
     4235            }
     4236        }
     4237        if(not @Contents) {
     4238            exitStatus("Error", "can't extract \'$Path\'");
     4239        }
     4240        return join_P($UnpackDir, $Contents[0]);
     4241    }
     4242    elsif($FileName=~s/\Q.tar.gz\E\Z//g)
     4243    { # *.tar.gz
     4244        if($In::Opt{"OS"} eq "windows")
     4245        { # -xvzf option is not implemented in tar.exe (2003)
     4246          # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
     4247            my $TarCmd = getCmdPath("tar");
     4248            if(not $TarCmd) {
     4249                exitStatus("Not_Found", "can't find \"tar\" command");
     4250            }
     4251            my $GzipCmd = getCmdPath("gzip");
     4252            if(not $GzipCmd) {
     4253                exitStatus("Not_Found", "can't find \"gzip\" command");
     4254            }
     4255            chdir($UnpackDir);
     4256            qx/$GzipCmd -k -d -f "$Path"/; # keep input files (-k)
     4257            if($?) {
     4258                exitStatus("Error", "can't extract \'$Path\'");
     4259            }
     4260            my @Contents = qx/$TarCmd -xvf "$Dir\\$FileName.tar"/;
     4261            if($? or not @Contents) {
     4262                exitStatus("Error", "can't extract \'$Path\'");
     4263            }
     4264            chdir($In::Opt{"OrigDir"});
     4265            unlink($Dir."/".$FileName.".tar");
     4266            chomp $Contents[0];
     4267            return join_P($UnpackDir, $Contents[0]);
     4268        }
     4269        else
     4270        { # Linux, Unix, OS X
     4271            my $TarCmd = getCmdPath("tar");
     4272            if(not $TarCmd) {
     4273                exitStatus("Not_Found", "can't find \"tar\" command");
     4274            }
     4275            chdir($UnpackDir);
     4276            my @Contents = qx/$TarCmd -xvzf "$Path" 2>&1/;
     4277            if($? or not @Contents) {
     4278                exitStatus("Error", "can't extract \'$Path\'");
     4279            }
     4280            chdir($In::Opt{"OrigDir"});
     4281            $Contents[0]=~s/^x //; # OS X
     4282            chomp $Contents[0];
     4283            return join_P($UnpackDir, $Contents[0]);
    86014284        }
    86024285    }
     
    86094292        $To = ".";
    86104293    }
    8611     if(not $Path or not -e $Path
    8612     or not -d $To) {
    8613         return "";
    8614     }
    8615     my ($From, $Name) = separate_path($Path);
    8616     if($OSgroup eq "windows")
     4294   
     4295    my $TmpDir = $In::Opt{"Tmp"};
     4296   
     4297    my ($From, $Name) = sepPath($Path);
     4298    if($In::Opt{"OS"} eq "windows")
    86174299    { # *.zip
    8618         my $ZipCmd = get_CmdPath("zip");
     4300        my $ZipCmd = getCmdPath("zip");
    86194301        if(not $ZipCmd) {
    86204302            exitStatus("Not_Found", "can't find \"zip\"");
     
    86234305        unlink($Pkg);
    86244306        chdir($To);
    8625         system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
     4307        system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TmpDir/null\"");
    86264308        if($?)
    86274309        { # cannot allocate memory (or other problems with "zip")
     
    86294311            exitStatus("Error", "can't pack the API dump: ".$!);
    86304312        }
    8631         chdir($ORIG_DIR);
     4313        chdir($In::Opt{"OrigDir"});
    86324314        unlink($Path);
    86334315        return $Pkg;
     
    86354317    else
    86364318    { # *.tar.gz
    8637         my $TarCmd = get_CmdPath("tar");
     4319        my $TarCmd = getCmdPath("tar");
    86384320        if(not $TarCmd) {
    86394321            exitStatus("Not_Found", "can't find \"tar\"");
    86404322        }
    8641         my $GzipCmd = get_CmdPath("gzip");
     4323        my $GzipCmd = getCmdPath("gzip");
    86424324        if(not $GzipCmd) {
    86434325            exitStatus("Not_Found", "can't find \"gzip\"");
     
    86524334            exitStatus("Error", "can't pack the API dump: ".$!);
    86534335        }
    8654         chdir($ORIG_DIR);
     4336        chdir($In::Opt{"OrigDir"});
    86554337        unlink($Path);
    86564338        return $To."/".$Name.".tar.gz";
     
    86584340}
    86594341
    8660 sub getMd5(@)
    8661 {
    8662     my $Md5 = md5_hex(@_);
    8663     return substr($Md5, 0, $MD5_LEN);
    8664 }
    8665 
    8666 sub scenario()
    8667 {
    8668     if($BinaryOnly and $SourceOnly)
    8669     { # both --binary and --source
    8670       # is the default mode
    8671         $DoubleReport = 1;
    8672         $JoinReport = 0;
    8673         $BinaryOnly = 0;
    8674         $SourceOnly = 0;
    8675         if($OutputReportPath)
    8676         { # --report-path
    8677             $DoubleReport = 0;
    8678             $JoinReport = 1;
    8679         }
    8680     }
    8681     elsif($BinaryOnly or $SourceOnly)
    8682     { # --binary or --source
    8683         $DoubleReport = 0;
    8684         $JoinReport = 0;
    8685     }
    8686     if(defined $Help)
    8687     {
    8688         HELP_MESSAGE();
    8689         exit(0);
    8690     }
    8691     if(defined $ShowVersion)
    8692     {
    8693         printMsg("INFO", "Java API Compliance Checker (JAPICC) $TOOL_VERSION\nCopyright (C) 2016 Andrey Ponomarenko's ABI Laboratory\nLicense: LGPL or GPL <http://www.gnu.org/licenses/>\nThis program is free software: you can redistribute it and/or modify it.\n\nWritten by Andrey Ponomarenko.");
    8694         exit(0);
    8695     }
    8696     if(defined $DumpVersion)
    8697     {
    8698         printMsg("INFO", $TOOL_VERSION);
    8699         exit(0);
    8700     }
    8701     $Data::Dumper::Sortkeys = 1;
    8702    
    8703     # FIXME: can't pass \&dump_sorting - cause a segfault sometimes
    8704     if($SortDump)
    8705     {
    8706         $Data::Dumper::Useperl = 1;
    8707         $Data::Dumper::Sortkeys = \&dump_sorting;
    8708     }
    8709    
    8710     if(defined $TestSystem)
    8711     {
    8712         detect_default_paths();
    8713         testSystem();
    8714         exit(0);
    8715     }
    8716    
    8717     if(defined $ShortMode)
    8718     {
    8719         if(not defined $AffectLimit) {
    8720             $AffectLimit = 10;
    8721         }
    8722     }
    8723    
    8724     if(not $TargetLibraryName and not $CountMethods)
    8725     {
    8726         if($DumpAPI)
    8727         {
    8728             if($DumpAPI=~/\.jar\Z/)
    8729             { # short usage
    8730                 my ($Name, $Version) = getPkgVersion(get_filename($DumpAPI));
    8731                 if($Name and $Version ne "")
    8732                 {
    8733                     $TargetLibraryName = $Name;
    8734                     if(not $TargetVersion{1}) {
    8735                         $TargetVersion{1} = $Version;
    8736                     }
    8737                 }
    8738             }
    8739         }
    8740         else
    8741         {
    8742             if($Descriptor{1}{"Path"}=~/\.jar\Z/ and $Descriptor{2}{"Path"}=~/\.jar\Z/)
    8743             { # short usage
    8744                 my ($Name1, $Version1) = getPkgVersion(get_filename($Descriptor{1}{"Path"}));
    8745                 my ($Name2, $Version2) = getPkgVersion(get_filename($Descriptor{2}{"Path"}));
    8746                
    8747                 if($Name1 and $Version1 ne ""
    8748                 and $Version2 ne "")
    8749                 {
    8750                     $TargetLibraryName = $Name1;
    8751                     if(not $TargetVersion{1}) {
    8752                         $TargetVersion{1} = $Version1;
    8753                     }
    8754                     if(not $TargetVersion{2}) {
    8755                         $TargetVersion{2} = $Version2;
    8756                     }
    8757                 }
    8758             }
    8759         }
    8760        
    8761         if(not $TargetLibraryName) {
    8762             exitStatus("Error", "library name is not selected (option --lib=NAME)");
     4342sub initAliases($)
     4343{
     4344    my $LVer = $_[0];
     4345   
     4346    initAPI($LVer);
     4347   
     4348    $MethodInfo{$LVer} = $In::API{$LVer}{"MethodInfo"};
     4349    $TypeInfo{$LVer} = $In::API{$LVer}{"TypeInfo"};
     4350    $TName_Tid{$LVer} = $In::API{$LVer}{"TName_Tid"};
     4351   
     4352    initAliases_TypeAttr($LVer);
     4353}
     4354
     4355sub createAPIFile($$)
     4356{
     4357    my ($LVer, $DescPath) = @_;
     4358   
     4359    if(not -e $DescPath) {
     4360        exitStatus("Access_Error", "can't access \'$DescPath\'");
     4361    }
     4362   
     4363    detectDefaultPaths("bin", "java");
     4364   
     4365    if(isDump($DescPath))
     4366    {
     4367        $In::API{$LVer} = readAPIDump($LVer, $DescPath, "Main");
     4368        initAliases($LVer);
     4369       
     4370        if(my $V = $In::Desc{$LVer}{"TargetVersion"}) {
     4371            $In::Desc{$LVer}{"Version"} = $V;
     4372        }
     4373        else {
     4374            $In::Desc{$LVer}{"Version"} = $In::API{$LVer}{"LibraryVersion"};
    87634375        }
    87644376    }
    87654377    else
    8766     { # validate library name
    8767         if($TargetLibraryName=~/[\*\/\\]/) {
    8768             exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
    8769         }
    8770     }
    8771     if(not $TargetTitle) {
    8772         $TargetTitle = $TargetLibraryName;
    8773     }
    8774     if($ClassListPath)
    8775     {
    8776         if(not -f $ClassListPath) {
    8777             exitStatus("Access_Error", "can't access file \'$ClassListPath\'");
    8778         }
    8779         foreach my $Class (split(/\n/, readFile($ClassListPath)))
    8780         {
    8781             $Class=~s/\//./g;
    8782             $ClassList_User{$Class} = 1;
    8783         }
    8784     }
    8785     if($AnnotationsListPath)
    8786     {
    8787         if(not -f $AnnotationsListPath) {
    8788             exitStatus("Access_Error", "can't access file \'$AnnotationsListPath\'");
    8789         }
    8790         foreach my $Annotation (split(/\n/, readFile($AnnotationsListPath)))
    8791         {
    8792             $AnnotationList_User{$Annotation} = 1;
    8793         }
    8794     }
    8795     if($SkipAnnotationsListPath)
    8796     {
    8797         if(not -f $SkipAnnotationsListPath) {
    8798             exitStatus("Access_Error", "can't access file \'$SkipAnnotationsListPath\'");
    8799         }
    8800         foreach my $Annotation (split(/\n/, readFile($SkipAnnotationsListPath)))
    8801         {
    8802             $SkipAnnotationList_User{$Annotation} = 1;
    8803         }
    8804     }
    8805     if($SkipClassesList)
    8806     {
    8807         if(not -f $SkipClassesList) {
    8808             exitStatus("Access_Error", "can't access file \'$SkipClassesList\'");
    8809         }
    8810         foreach my $Class (split(/\n/, readFile($SkipClassesList)))
    8811         {
    8812             $Class=~s/\//./g;
    8813             $SkipClasses{$Class} = 1;
    8814         }
    8815     }
    8816     if($SkipPackagesList)
    8817     {
    8818         if(not -f $SkipPackagesList) {
    8819             exitStatus("Access_Error", "can't access file \'$SkipPackagesList\'");
    8820         }
    8821         foreach my $Package (split(/\n/, readFile($SkipPackagesList)))
    8822         {
    8823             $SkipPackages{1}{$Package} = 1;
    8824             $SkipPackages{2}{$Package} = 1;
    8825         }
    8826     }
    8827     if($ClientPath)
    8828     {
    8829         if($ClientPath=~/\.class\Z/) {
    8830             exitStatus("Error", "input file is not a java archive");
    8831         }
    8832        
    8833         if(-f $ClientPath)
    8834         {
    8835             detect_default_paths();
    8836             readArchive(0, $ClientPath)
    8837         }
    8838         else {
    8839             exitStatus("Access_Error", "can't access file \'$ClientPath\'");
    8840         }
    8841     }
    8842    
    8843     if($CountMethods)
    8844     {
    8845         if(not -e $CountMethods) {
    8846             exitStatus("Access_Error", "can't access \'$CountMethods\'");
    8847         }
    8848        
    8849         read_API_Dump(1, $CountMethods, "Main");
    8850        
    8851         my $Count = 0;
    8852         foreach my $Method (keys(%{$MethodInfo{1}})) {
    8853             $Count += methodFilter($Method, 1);
    8854         }
    8855        
    8856         printMsg("INFO", $Count);
    8857         exit(0);
    8858     }
    8859    
    8860     if($DumpAPI)
    8861     {
    8862         if(not -e $DumpAPI) {
    8863             exitStatus("Access_Error", "can't access \'$DumpAPI\'");
    8864         }
    8865        
    8866         detect_default_paths();
    8867         checkVersionNum(1, $DumpAPI);
    8868        
    8869         my $TarCmd = get_CmdPath("tar");
     4378    {
     4379        loadModule("APIDump");
     4380   
     4381        checkVersionNum($LVer, $DescPath);
     4382        readDesc(createDesc($DescPath, $LVer), $LVer);
     4383       
     4384        initLogging($LVer);
     4385       
     4386        createAPIDump($LVer);
     4387    }
     4388   
     4389    if(my $Dep = $In::Desc{$LVer}{"DepDump"}) {
     4390        mergeAPIs($LVer, readAPIDump($LVer, $Dep, "Dep"));
     4391    }
     4392   
     4393    printMsg("INFO", "Creating library API dump ...");
     4394   
     4395    $In::API{$LVer}{"API_DUMP_VERSION"} = $API_DUMP_VERSION;
     4396    $In::API{$LVer}{"JAPI_COMPLIANCE_CHECKER_VERSION"} = $TOOL_VERSION;
     4397   
     4398    foreach ("TName_Tid") {
     4399        delete($In::API{$LVer}{$_});
     4400    }
     4401   
     4402    my $DumpPath = "api_dumps/".$In::Opt{"TargetLib"}."/".$In::Desc{$LVer}{"Version"}."/API.dump";
     4403    if($In::Opt{"OutputDumpPath"})
     4404    { # user defined path
     4405        $DumpPath = $In::Opt{"OutputDumpPath"};
     4406    }
     4407   
     4408    my $ArExt = $In::Opt{"Ar"};
     4409    my $Archive = ($DumpPath=~s/\Q.$ArExt\E\Z//g);
     4410   
     4411    if($Archive)
     4412    {
     4413        my $TarCmd = getCmdPath("tar");
    88704414        if(not $TarCmd) {
    88714415            exitStatus("Not_Found", "can't find \"tar\"");
    88724416        }
    8873         my $GzipCmd = get_CmdPath("gzip");
     4417        my $GzipCmd = getCmdPath("gzip");
    88744418        if(not $GzipCmd) {
    88754419            exitStatus("Not_Found", "can't find \"gzip\"");
    88764420        }
    8877         createDescriptor(1, $DumpAPI);
    8878         if(not $Descriptor{1}{"Archives"}) {
    8879             exitStatus("Error", "descriptor does not contain Java ARchives");
    8880         }
     4421    }
     4422   
     4423    my ($DDir, $DName) = sepPath($DumpPath);
     4424    my $DPath = $In::Opt{"Tmp"}."/".$DName;
     4425    if(not $Archive) {
     4426        $DPath = $DumpPath;
     4427    }
     4428   
     4429    mkpath($DDir);
     4430   
     4431    open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
     4432    print DUMP Dumper($In::API{$LVer});
     4433    close(DUMP);
     4434   
     4435    if(not -s $DPath) {
     4436        exitStatus("Error", "can't create API dump because something is going wrong with the Data::Dumper module");
     4437    }
     4438   
     4439    if($Archive) {
     4440        $DumpPath = createArchive($DPath, $DDir);
     4441    }
     4442   
     4443    if($In::Opt{"OutputDumpPath"}) {
     4444        printMsg("INFO", "Dump path: ".$In::Opt{"OutputDumpPath"});
     4445    }
     4446    else {
     4447        printMsg("INFO", "Dump path: $DumpPath");
     4448    }
     4449    exit(0);
     4450}
     4451
     4452sub compareInit()
     4453{
     4454    if(not $In::Desc{1}{"Path"}) {
     4455        exitStatus("Error", "-old option is not specified");
     4456    }
     4457    if(not -e $In::Desc{1}{"Path"}) {
     4458        exitStatus("Access_Error", "can't access \'".$In::Desc{1}{"Path"}."\'");
     4459    }
     4460    if(not $In::Desc{2}{"Path"}) {
     4461        exitStatus("Error", "-new option is not specified");
     4462    }
     4463    if(not -e $In::Desc{2}{"Path"}) {
     4464        exitStatus("Access_Error", "can't access \'".$In::Desc{2}{"Path"}."\'");
     4465    }
     4466   
     4467    if($In::Opt{"Quick"})
     4468    {
     4469        $CompatRules{"Binary"}{"Interface_Added_Super_Interface"}{"Severity"} = "Low";
     4470        $CompatRules{"Binary"}{"Abstract_Class_Added_Super_Abstract_Class"}{"Severity"} = "Low";
     4471        $CompatRules{"Binary"}{"Abstract_Class_Added_Super_Interface"}{"Severity"} = "Low";
     4472        $CompatRules{"Binary"}{"Abstract_Class_Added_Abstract_Method"}{"Severity"} = "Low";
     4473        $CompatRules{"Binary"}{"Interface_Added_Abstract_Method"}{"Severity"} = "Low";
     4474    }
     4475   
     4476    printMsg("INFO", "Preparing, please wait ...");
     4477   
     4478    detectDefaultPaths("bin", undef);
     4479   
     4480    if(isDump($In::Desc{1}{"Path"}))
     4481    {
     4482        $In::API{1} = readAPIDump(1, $In::Desc{1}{"Path"}, "Main");
     4483        initAliases(1);
     4484       
     4485        if(my $V = $In::Desc{1}{"TargetVersion"}) {
     4486            $In::Desc{1}{"Version"} = $V;
     4487        }
     4488        else {
     4489            $In::Desc{1}{"Version"} = $In::API{1}{"LibraryVersion"};
     4490        }
     4491    }
     4492    else
     4493    {
     4494        loadModule("APIDump");
     4495       
     4496        checkVersionNum(1, $In::Desc{1}{"Path"});
     4497        readDesc(createDesc($In::Desc{1}{"Path"}, 1), 1);
    88814498       
    88824499        initLogging(1);
    8883         readArchives(1);
    8884        
    8885         printMsg("INFO", "creating library API dump ...");
    8886         if(not keys(%{$MethodInfo{1}})) {
    8887             printMsg("WARNING", "empty dump");
    8888         }
    8889        
    8890         my $MInfo = {};
    8891         my $MNum = 0;
    8892         foreach my $Method (sort keys(%{$MethodInfo{1}}))
    8893         {
    8894             my $MId = $MNum;
    8895             if($REPRODUCIBLE) {
    8896                 $MId = getMd5($Method);
    8897             }
    8898             $MInfo->{$MId} = $MethodInfo{1}{$Method};
    8899             $MInfo->{$MId}{"Name"} = $Method;
    8900            
    8901             $MNum+=1;
    8902         }
    8903        
    8904         my $MUsed = {};
    8905         $MNum = 0;
    8906         foreach my $Inv (sort keys(%{$MethodUsed{1}}))
    8907         {
    8908             my $MId = $MNum;
    8909             if($REPRODUCIBLE) {
    8910                 $MId = getMd5($Inv);
    8911             }
    8912            
    8913             $MUsed->{$MId}{"Name"} = $Inv;
    8914             $MUsed->{$MId}{"Used"} = $MethodUsed{1}{$Inv};
    8915            
    8916             $MNum+=1;
    8917         }
    8918        
    8919         my %API = (
    8920             "MethodInfo" => $MInfo,
    8921             "TypeInfo" => $TypeInfo{1},
    8922             "MethodUsed" => $MUsed,
    8923             # "FieldUsed" => $FieldUsed{1},
    8924             "LibraryVersion" => $Descriptor{1}{"Version"},
    8925             "LibraryName" => $TargetLibraryName,
    8926             "Language" => "Java",
    8927             "API_DUMP_VERSION" => $API_DUMP_VERSION,
    8928             "JAPI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
    8929         );
    8930        
    8931         my $DumpPath = "api_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{1}{"Version"}.".api.".$AR_EXT;
    8932         if($OutputDumpPath)
    8933         { # user defined path
    8934             $DumpPath = $OutputDumpPath;
    8935         }
    8936        
    8937         my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
    8938        
    8939         my ($DDir, $DName) = separate_path($DumpPath);
    8940         my $DPath = $TMP_DIR."/".$DName;
    8941         if(not $Archive) {
    8942             $DPath = $DumpPath;
    8943         }
    8944        
    8945         mkpath($DDir);
    8946        
    8947         open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
    8948         print DUMP Dumper(\%API);
    8949         close(DUMP);
    8950        
    8951         if(not -s $DPath) {
    8952             exitStatus("Error", "can't create API dump because something is going wrong with the Data::Dumper module");
    8953         }
    8954        
    8955         if($Archive) {
    8956             $DumpPath = createArchive($DPath, $DDir);
    8957         }
    8958        
    8959         if($OutputDumpPath) {
    8960             printMsg("INFO", "dump path: $OutputDumpPath");
     4500        detectDefaultPaths(undef, "java");
     4501        createAPIDump(1);
     4502    }
     4503   
     4504    if(my $Dep = $In::Desc{1}{"DepDump"}) {
     4505        mergeAPIs(1, readAPIDump(1, $Dep, "Dep"));
     4506    }
     4507   
     4508    if(isDump($In::Desc{2}{"Path"}))
     4509    {
     4510        $In::API{2} = readAPIDump(2, $In::Desc{2}{"Path"}, "Main");
     4511        initAliases(2);
     4512       
     4513        if(my $V = $In::Desc{2}{"TargetVersion"}) {
     4514            $In::Desc{2}{"Version"} = $V;
    89614515        }
    89624516        else {
    8963             printMsg("INFO", "dump path: $DumpPath");
    8964         }
    8965         exit(0);
    8966     }
    8967     if(not $Descriptor{1}{"Path"}) {
    8968         exitStatus("Error", "-old option is not specified");
    8969     }
    8970     if(not -e $Descriptor{1}{"Path"}) {
    8971         exitStatus("Access_Error", "can't access \'".$Descriptor{1}{"Path"}."\'");
    8972     }
    8973     if(not $Descriptor{2}{"Path"}) {
    8974         exitStatus("Error", "-new option is not specified");
    8975     }
    8976     if(not -e $Descriptor{2}{"Path"}) {
    8977         exitStatus("Access_Error", "can't access \'".$Descriptor{2}{"Path"}."\'");
    8978     }
    8979    
    8980     if($Quick)
    8981     {
    8982         $TypeProblems_Kind{"Binary"}{"Interface_Added_Super_Interface"} = "Low";
    8983         $TypeProblems_Kind{"Binary"}{"Abstract_Class_Added_Super_Abstract_Class"} = "Low";
    8984         $TypeProblems_Kind{"Binary"}{"Abstract_Class_Added_Super_Interface"} = "Low";
    8985         $TypeProblems_Kind{"Binary"}{"Abstract_Class_Added_Abstract_Method"} = "Low";
    8986         $TypeProblems_Kind{"Binary"}{"Interface_Added_Abstract_Method"} = "Low";
    8987     }
    8988    
    8989     detect_default_paths();
    8990    
    8991     checkVersionNum(1, $Descriptor{1}{"Path"});
    8992     checkVersionNum(2, $Descriptor{2}{"Path"});
    8993    
    8994     createDescriptor(1, $Descriptor{1}{"Path"});
    8995     createDescriptor(2, $Descriptor{2}{"Path"});
    8996    
    8997     if(not $Descriptor{1}{"Archives"}) {
    8998         exitStatus("Error", "descriptor d1 does not contain Java ARchives");
    8999     }
    9000     if(not $Descriptor{2}{"Archives"}) {
    9001         exitStatus("Error", "descriptor d2 does not contain Java ARchives");
    9002     }
    9003     initLogging(1);
    9004     initLogging(2);
    9005    
    9006     if($Descriptor{1}{"Archives"}
    9007     and not $Descriptor{1}{"Dump"}) {
    9008         readArchives(1);
    9009     }
    9010     if($Descriptor{2}{"Archives"}
    9011     and not $Descriptor{2}{"Dump"}) {
    9012         readArchives(2);
    9013     }
     4517            $In::Desc{2}{"Version"} = $In::API{2}{"LibraryVersion"};
     4518        }
     4519    }
     4520    else
     4521    {
     4522        loadModule("APIDump");
     4523       
     4524        checkVersionNum(2, $In::Desc{2}{"Path"});
     4525        readDesc(createDesc($In::Desc{2}{"Path"}, 2), 2);
     4526       
     4527        initLogging(2);
     4528        detectDefaultPaths(undef, "java");
     4529        createAPIDump(2);
     4530    }
     4531   
     4532    if(my $Dep = $In::Desc{2}{"DepDump"}) {
     4533        mergeAPIs(2, readAPIDump(2, $Dep, "Dep"));
     4534    }
     4535   
     4536    prepareData(1);
     4537    prepareData(2);
    90144538   
    90154539    foreach my $Inv (keys(%{$MethodUsed{2}}))
     
    90594583        }
    90604584    }
    9061    
    9062     prepareMethods(1);
    9063     prepareMethods(2);
     4585}
     4586
     4587sub scenario()
     4588{
     4589    setTarget("default");
     4590   
     4591    initAliases(1);
     4592    initAliases(2);
     4593   
     4594    $In::Opt{"OrigDir"} = cwd();
     4595    $In::Opt{"Tmp"} = tempdir(CLEANUP=>1);
     4596    $In::Opt{"Reproducible"} = 1;
     4597   
     4598    $In::Opt{"JoinReport"} = 1;
     4599    $In::Opt{"DoubleReport"} = 0;
     4600   
     4601    if($In::Opt{"BinaryOnly"} and $In::Opt{"SourceOnly"})
     4602    { # both --binary and --source
     4603      # is the default mode
     4604        $In::Opt{"DoubleReport"} = 1;
     4605        $In::Opt{"JoinReport"} = 0;
     4606        $In::Opt{"BinaryOnly"} = 0;
     4607        $In::Opt{"SourceOnly"} = 0;
     4608        if($In::Opt{"OutputReportPath"})
     4609        { # --report-path
     4610            $In::Opt{"DoubleReport"} = 0;
     4611            $In::Opt{"JoinReport"} = 1;
     4612        }
     4613    }
     4614    elsif($In::Opt{"BinaryOnly"} or $In::Opt{"SourceOnly"})
     4615    { # --binary or --source
     4616        $In::Opt{"DoubleReport"} = 0;
     4617        $In::Opt{"JoinReport"} = 0;
     4618    }
     4619    if(defined $In::Opt{"Help"})
     4620    {
     4621        helpMsg();
     4622        exit(0);
     4623    }
     4624    if(defined $In::Opt{"ShowVersion"})
     4625    {
     4626        printMsg("INFO", "Java API Compliance Checker (JAPICC) $TOOL_VERSION\nCopyright (C) 2017 Andrey Ponomarenko's ABI Laboratory\nLicense: LGPL or GPL <http://www.gnu.org/licenses/>\nThis program is free software: you can redistribute it and/or modify it.\n\nWritten by Andrey Ponomarenko.");
     4627        exit(0);
     4628    }
     4629    if(defined $In::Opt{"DumpVersion"})
     4630    {
     4631        printMsg("INFO", $TOOL_VERSION);
     4632        exit(0);
     4633    }
     4634    $Data::Dumper::Sortkeys = 1;
     4635   
     4636    # FIXME: can't pass \&dumpSorting - cause a segfault sometimes
     4637    if($In::Opt{"SortDump"})
     4638    {
     4639        $Data::Dumper::Useperl = 1;
     4640        $Data::Dumper::Sortkeys = \&dumpSorting;
     4641    }
     4642   
     4643    if(defined $In::Opt{"TestTool"})
     4644    {
     4645        detectDefaultPaths("bin", "java");
     4646        loadModule("RegTests");
     4647        testTool();
     4648        exit(0);
     4649    }
     4650   
     4651    if(defined $In::Opt{"ShortMode"})
     4652    {
     4653        if(not defined $In::Opt{"AffectLimit"}) {
     4654            $In::Opt{"AffectLimit"} = 10;
     4655        }
     4656    }
     4657   
     4658    if(not $In::Opt{"TargetLib"} and not $In::Opt{"CountMethods"})
     4659    {
     4660        if($In::Opt{"DumpAPI"})
     4661        {
     4662            if($In::Opt{"DumpAPI"}=~/\.jar\Z/)
     4663            { # short usage
     4664                my ($Name, $Version) = getPkgVersion(getFilename($In::Opt{"DumpAPI"}));
     4665                if($Name and $Version ne "")
     4666                {
     4667                    $In::Opt{"TargetLib"} = $Name;
     4668                    if(not $In::Desc{1}{"TargetVersion"}) {
     4669                        $In::Desc{1}{"TargetVersion"} = $Version;
     4670                    }
     4671                }
     4672            }
     4673        }
     4674        else
     4675        {
     4676            if($In::Desc{1}{"Path"}=~/\.jar\Z/ and $In::Desc{2}{"Path"}=~/\.jar\Z/)
     4677            { # short usage
     4678                my ($Name1, $Version1) = getPkgVersion(getFilename($In::Desc{1}{"Path"}));
     4679                my ($Name2, $Version2) = getPkgVersion(getFilename($In::Desc{2}{"Path"}));
     4680               
     4681                if($Name1 and $Version1 ne ""
     4682                and $Version2 ne "")
     4683                {
     4684                    $In::Opt{"TargetLib"} = $Name1;
     4685                    if(not $In::Desc{1}{"TargetVersion"}) {
     4686                        $In::Desc{1}{"TargetVersion"} = $Version1;
     4687                    }
     4688                    if(not $In::Desc{2}{"TargetVersion"}) {
     4689                        $In::Desc{2}{"TargetVersion"} = $Version2;
     4690                    }
     4691                }
     4692            }
     4693        }
     4694       
     4695        if(not $In::Opt{"TargetLib"}) {
     4696            exitStatus("Error", "library name is not selected (option --lib=NAME)");
     4697        }
     4698    }
     4699    else
     4700    { # validate library name
     4701        if($In::Opt{"TargetLib"}=~/[\*\/\\]/) {
     4702            exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
     4703        }
     4704    }
     4705    if(not $In::Opt{"TargetTitle"}) {
     4706        $In::Opt{"TargetTitle"} = $In::Opt{"TargetLib"};
     4707    }
     4708    if(my $ClassListPath = $In::Opt{"ClassListPath"})
     4709    {
     4710        if(not -f $ClassListPath) {
     4711            exitStatus("Access_Error", "can't access file \'$ClassListPath\'");
     4712        }
     4713        foreach my $Class (split(/\n/, readFile($ClassListPath)))
     4714        {
     4715            $Class=~s/\//./g;
     4716            $In::Opt{"ClassList_User"}{$Class} = 1;
     4717        }
     4718    }
     4719    if(my $AnnotationsListPath = $In::Opt{"AnnotationsListPath"})
     4720    {
     4721        if(not -f $AnnotationsListPath) {
     4722            exitStatus("Access_Error", "can't access file \'$AnnotationsListPath\'");
     4723        }
     4724        foreach my $Annotation (split(/\n/, readFile($AnnotationsListPath)))
     4725        {
     4726            $In::Opt{"AnnotationList_User"}{$Annotation} = 1;
     4727        }
     4728    }
     4729    if(my $SkipAnnotationsListPath = $In::Opt{"SkipAnnotationsListPath"})
     4730    {
     4731        if(not -f $SkipAnnotationsListPath) {
     4732            exitStatus("Access_Error", "can't access file \'$SkipAnnotationsListPath\'");
     4733        }
     4734        foreach my $Annotation (split(/\n/, readFile($SkipAnnotationsListPath)))
     4735        {
     4736            $In::Opt{"SkipAnnotationList_User"}{$Annotation} = 1;
     4737        }
     4738    }
     4739    if(my $SkipClassesList = $In::Opt{"SkipClassesList"})
     4740    {
     4741        if(not -f $SkipClassesList) {
     4742            exitStatus("Access_Error", "can't access file \'$SkipClassesList\'");
     4743        }
     4744        foreach my $Class (split(/\n/, readFile($SkipClassesList)))
     4745        {
     4746            $Class=~s/\//./g;
     4747            $In::Opt{"SkipClasses"}{$Class} = 1;
     4748        }
     4749    }
     4750    if(my $SkipPackagesList = $In::Opt{"SkipPackagesList"})
     4751    {
     4752        if(not -f $SkipPackagesList) {
     4753            exitStatus("Access_Error", "can't access file \'$SkipPackagesList\'");
     4754        }
     4755        foreach my $Package (split(/\n/, readFile($SkipPackagesList)))
     4756        {
     4757            $In::Desc{1}{"SkipPackages"}{$Package} = 1;
     4758            $In::Desc{2}{"SkipPackages"}{$Package} = 1;
     4759        }
     4760    }
     4761    if(my $ClientPath = $In::Opt{"ClientPath"})
     4762    {
     4763        if($ClientPath=~/\.class\Z/) {
     4764            exitStatus("Error", "input file is not a java archive");
     4765        }
     4766       
     4767        if(-f $ClientPath)
     4768        {
     4769            detectDefaultPaths("bin", undef);
     4770            readArchive(0, $ClientPath)
     4771        }
     4772        else {
     4773            exitStatus("Access_Error", "can't access file \'$ClientPath\'");
     4774        }
     4775    }
     4776   
     4777    if(my $DPath = $In::Opt{"CountMethods"})
     4778    {
     4779        if(not -e $DPath) {
     4780            exitStatus("Access_Error", "can't access \'$DPath\'");
     4781        }
     4782       
     4783        $In::API{1} = readAPIDump(1, $DPath, "Main");
     4784        initAliases(1);
     4785       
     4786        my $Count = 0;
     4787        foreach my $Method (keys(%{$MethodInfo{1}})) {
     4788            $Count += methodFilter($Method, 1);
     4789        }
     4790       
     4791        printMsg("INFO", $Count);
     4792        exit(0);
     4793    }
     4794   
     4795    if($In::Opt{"DumpAPI"})
     4796    {
     4797        createAPIFile(1, $In::Opt{"DumpAPI"});
     4798        exit(0);
     4799    }
     4800   
     4801    compareInit();
     4802   
     4803    readRules("Binary");
     4804    readRules("Source");
    90644805   
    90654806    detectAdded();
    90664807    detectRemoved();
    90674808   
    9068     printMsg("INFO", "comparing classes ...");
     4809    printMsg("INFO", "Comparing classes ...");
    90694810    mergeClasses();
    90704811    mergeMethods();
    90714812   
    9072     foreach my $M (keys(%CompatProblems))
    9073     {
    9074         foreach my $K (keys(%{$CompatProblems{$M}}))
    9075         {
    9076             foreach my $L (keys(%{$CompatProblems{$M}{$K}}))
    9077             {
    9078                 if(my $T = $CompatProblems{$M}{$K}{$L}{"Type_Name"}) {
    9079                     $TypeProblemsIndex{$T}{$M} = 1;
    9080                 }
    9081             }
    9082         }
    9083     }
    9084    
    90854813    printReport();
    90864814   
    90874815    if($RESULT{"Source"}{"Problems"} + $RESULT{"Binary"}{"Problems"}) {
    9088         exit($ERROR_CODE{"Incompatible"});
     4816        exit(getErrorCode("Incompatible"));
    90894817    }
    90904818    else {
    9091         exit($ERROR_CODE{"Compatible"});
     4819        exit(getErrorCode("Compatible"));
    90924820    }
    90934821}
Note: See TracChangeset for help on using the changeset viewer.